@anuma/sdk 6.33.2 → 6.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +1099 -293
- package/dist/expo/index.d.mts +218 -4
- package/dist/expo/index.d.ts +218 -4
- package/dist/expo/index.mjs +1095 -293
- package/dist/index.cjs +18 -6
- package/dist/index.mjs +18 -6
- package/dist/react/index.cjs +1180 -374
- package/dist/react/index.d.mts +251 -4
- package/dist/react/index.d.ts +251 -4
- package/dist/react/index.mjs +1176 -374
- package/dist/server/index.cjs +118 -86
- package/dist/server/index.d.mts +77 -3
- package/dist/server/index.d.ts +77 -3
- package/dist/server/index.mjs +118 -86
- package/dist/telemetry/index.d.mts +3 -4
- package/dist/telemetry/index.d.ts +3 -4
- package/dist/tools/selection/index.cjs +18 -6
- package/dist/tools/selection/index.mjs +18 -6
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -1740,10 +1740,10 @@ function parsePlaintextToken(raw, walletAddress) {
|
|
|
1740
1740
|
return null;
|
|
1741
1741
|
}
|
|
1742
1742
|
if (!parsed || typeof parsed !== "object") return null;
|
|
1743
|
-
const
|
|
1744
|
-
const data =
|
|
1743
|
+
const record2 = parsed;
|
|
1744
|
+
const data = record2.token?.accessToken ? record2.token : record2;
|
|
1745
1745
|
if (!data?.accessToken) return null;
|
|
1746
|
-
if (
|
|
1746
|
+
if (record2.wallet && record2.wallet !== walletAddress) return null;
|
|
1747
1747
|
return data;
|
|
1748
1748
|
}
|
|
1749
1749
|
function promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress) {
|
|
@@ -1867,8 +1867,8 @@ async function storeTokenData(data, walletAddress) {
|
|
|
1867
1867
|
getLogger().warn("Failed to encrypt GitHub OAuth token:", error);
|
|
1868
1868
|
}
|
|
1869
1869
|
}
|
|
1870
|
-
const
|
|
1871
|
-
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(
|
|
1870
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
1871
|
+
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(record2));
|
|
1872
1872
|
}
|
|
1873
1873
|
function clearGithubToken(walletAddress) {
|
|
1874
1874
|
if (typeof window === "undefined") return;
|
|
@@ -1917,17 +1917,17 @@ function storeOAuthState(state) {
|
|
|
1917
1917
|
}
|
|
1918
1918
|
function getAndClearOAuthState() {
|
|
1919
1919
|
if (typeof window === "undefined") return null;
|
|
1920
|
-
const
|
|
1920
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY);
|
|
1921
1921
|
sessionStorage.removeItem(CODE_STORAGE_KEY);
|
|
1922
|
-
if (!
|
|
1922
|
+
if (!stored2) return null;
|
|
1923
1923
|
try {
|
|
1924
|
-
const parsed = JSON.parse(
|
|
1924
|
+
const parsed = JSON.parse(stored2);
|
|
1925
1925
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
1926
1926
|
return parsed.state;
|
|
1927
1927
|
}
|
|
1928
1928
|
} catch {
|
|
1929
1929
|
}
|
|
1930
|
-
return
|
|
1930
|
+
return stored2;
|
|
1931
1931
|
}
|
|
1932
1932
|
function isGithubCallback(callbackPath) {
|
|
1933
1933
|
if (typeof window === "undefined") return false;
|
|
@@ -2219,8 +2219,8 @@ async function storeTokenData2(data, walletAddress) {
|
|
|
2219
2219
|
getLogger().warn("Failed to encrypt Calendar OAuth token:", error);
|
|
2220
2220
|
}
|
|
2221
2221
|
}
|
|
2222
|
-
const
|
|
2223
|
-
sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(
|
|
2222
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
2223
|
+
sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(record2));
|
|
2224
2224
|
}
|
|
2225
2225
|
function clearCalendarToken(walletAddress) {
|
|
2226
2226
|
if (typeof window === "undefined") return;
|
|
@@ -2260,17 +2260,17 @@ function getRedirectUri2(callbackPath) {
|
|
|
2260
2260
|
}
|
|
2261
2261
|
function getAndClearOAuthState2() {
|
|
2262
2262
|
if (typeof window === "undefined") return null;
|
|
2263
|
-
const
|
|
2263
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY2);
|
|
2264
2264
|
sessionStorage.removeItem(CODE_STORAGE_KEY2);
|
|
2265
|
-
if (!
|
|
2265
|
+
if (!stored2) return null;
|
|
2266
2266
|
try {
|
|
2267
|
-
const parsed = JSON.parse(
|
|
2267
|
+
const parsed = JSON.parse(stored2);
|
|
2268
2268
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
2269
2269
|
return parsed.state;
|
|
2270
2270
|
}
|
|
2271
2271
|
} catch {
|
|
2272
2272
|
}
|
|
2273
|
-
return
|
|
2273
|
+
return stored2;
|
|
2274
2274
|
}
|
|
2275
2275
|
function isCalendarCallback(callbackPath) {
|
|
2276
2276
|
if (typeof window === "undefined") return false;
|
|
@@ -2544,8 +2544,8 @@ async function storeTokenData3(data, walletAddress) {
|
|
|
2544
2544
|
getLogger().warn("Failed to encrypt Drive OAuth token:", error);
|
|
2545
2545
|
}
|
|
2546
2546
|
}
|
|
2547
|
-
const
|
|
2548
|
-
sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(
|
|
2547
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
2548
|
+
sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(record2));
|
|
2549
2549
|
}
|
|
2550
2550
|
function clearDriveToken(walletAddress) {
|
|
2551
2551
|
if (typeof window === "undefined") return;
|
|
@@ -2585,17 +2585,17 @@ function getRedirectUri3(callbackPath) {
|
|
|
2585
2585
|
}
|
|
2586
2586
|
function getAndClearOAuthState3() {
|
|
2587
2587
|
if (typeof window === "undefined") return null;
|
|
2588
|
-
const
|
|
2588
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY3);
|
|
2589
2589
|
sessionStorage.removeItem(CODE_STORAGE_KEY3);
|
|
2590
|
-
if (!
|
|
2590
|
+
if (!stored2) return null;
|
|
2591
2591
|
try {
|
|
2592
|
-
const parsed = JSON.parse(
|
|
2592
|
+
const parsed = JSON.parse(stored2);
|
|
2593
2593
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
2594
2594
|
return parsed.state;
|
|
2595
2595
|
}
|
|
2596
2596
|
} catch {
|
|
2597
2597
|
}
|
|
2598
|
-
return
|
|
2598
|
+
return stored2;
|
|
2599
2599
|
}
|
|
2600
2600
|
function isDriveCallback(callbackPath) {
|
|
2601
2601
|
if (typeof window === "undefined") return false;
|
|
@@ -2924,11 +2924,11 @@ function storePKCEState(pkce) {
|
|
|
2924
2924
|
}
|
|
2925
2925
|
function getAndClearPKCEState() {
|
|
2926
2926
|
if (typeof window === "undefined") return null;
|
|
2927
|
-
const
|
|
2927
|
+
const stored2 = sessionStorage.getItem(PKCE_STORAGE_KEY);
|
|
2928
2928
|
sessionStorage.removeItem(PKCE_STORAGE_KEY);
|
|
2929
|
-
if (!
|
|
2929
|
+
if (!stored2) return null;
|
|
2930
2930
|
try {
|
|
2931
|
-
return JSON.parse(
|
|
2931
|
+
return JSON.parse(stored2);
|
|
2932
2932
|
} catch {
|
|
2933
2933
|
return null;
|
|
2934
2934
|
}
|
|
@@ -2946,8 +2946,8 @@ async function storeTokenData4(data, walletAddress) {
|
|
|
2946
2946
|
} catch {
|
|
2947
2947
|
}
|
|
2948
2948
|
}
|
|
2949
|
-
const
|
|
2950
|
-
sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(
|
|
2949
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
2950
|
+
sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(record2));
|
|
2951
2951
|
}
|
|
2952
2952
|
async function getStoredTokenData4(walletAddress) {
|
|
2953
2953
|
if (typeof window === "undefined") return null;
|
|
@@ -2963,12 +2963,12 @@ async function getStoredTokenData4(walletAddress) {
|
|
|
2963
2963
|
cachedWalletAddress4 = null;
|
|
2964
2964
|
}
|
|
2965
2965
|
try {
|
|
2966
|
-
const
|
|
2967
|
-
if (
|
|
2966
|
+
const stored2 = localStorage.getItem(getTokenStorageKey4(walletAddress));
|
|
2967
|
+
if (stored2?.startsWith(ENCRYPTED_PREFIX5)) {
|
|
2968
2968
|
if (walletAddress && hasEncryptionKey(walletAddress)) {
|
|
2969
2969
|
try {
|
|
2970
2970
|
const cryptoKey = await getEncryptionKey(walletAddress);
|
|
2971
|
-
const encrypted =
|
|
2971
|
+
const encrypted = stored2.slice(ENCRYPTED_PREFIX5.length);
|
|
2972
2972
|
const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
|
|
2973
2973
|
const data = JSON.parse(decrypted);
|
|
2974
2974
|
if (data.accessToken) return data;
|
|
@@ -3077,12 +3077,12 @@ async function getClientRegistration(walletAddress) {
|
|
|
3077
3077
|
if (typeof window === "undefined") return null;
|
|
3078
3078
|
try {
|
|
3079
3079
|
const scopedKey = getClientRegistrationStorageKey(walletAddress);
|
|
3080
|
-
const
|
|
3081
|
-
if (
|
|
3080
|
+
const stored2 = localStorage.getItem(scopedKey);
|
|
3081
|
+
if (stored2?.startsWith(ENCRYPTED_PREFIX5)) {
|
|
3082
3082
|
if (walletAddress && hasEncryptionKey(walletAddress)) {
|
|
3083
3083
|
try {
|
|
3084
3084
|
const cryptoKey = await getEncryptionKey(walletAddress);
|
|
3085
|
-
const encrypted =
|
|
3085
|
+
const encrypted = stored2.slice(ENCRYPTED_PREFIX5.length);
|
|
3086
3086
|
const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
|
|
3087
3087
|
const data = JSON.parse(decrypted);
|
|
3088
3088
|
if (data.clientId) {
|
|
@@ -3092,8 +3092,8 @@ async function getClientRegistration(walletAddress) {
|
|
|
3092
3092
|
}
|
|
3093
3093
|
}
|
|
3094
3094
|
}
|
|
3095
|
-
if (
|
|
3096
|
-
const data = JSON.parse(
|
|
3095
|
+
if (stored2 && !stored2.startsWith(ENCRYPTED_PREFIX5)) {
|
|
3096
|
+
const data = JSON.parse(stored2);
|
|
3097
3097
|
if (!data.clientId) return null;
|
|
3098
3098
|
return data;
|
|
3099
3099
|
}
|
|
@@ -4934,13 +4934,13 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
4934
4934
|
const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
4935
4935
|
return Promise.all(
|
|
4936
4936
|
topK.map(async ({ message, similarity }) => {
|
|
4937
|
-
const
|
|
4937
|
+
const stored2 = await messageRawToStored(
|
|
4938
4938
|
message,
|
|
4939
4939
|
ctx.walletAddress,
|
|
4940
4940
|
ctx.signMessage,
|
|
4941
4941
|
ctx.embeddedWalletSigner
|
|
4942
4942
|
);
|
|
4943
|
-
return { ...
|
|
4943
|
+
return { ...stored2, similarity };
|
|
4944
4944
|
})
|
|
4945
4945
|
);
|
|
4946
4946
|
}
|
|
@@ -5044,13 +5044,13 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
5044
5044
|
const storedById = new Map(
|
|
5045
5045
|
await Promise.all(
|
|
5046
5046
|
Array.from(uniqueMessages, async ([id, m]) => {
|
|
5047
|
-
const
|
|
5047
|
+
const stored2 = await messageRawToStored(
|
|
5048
5048
|
m,
|
|
5049
5049
|
ctx.walletAddress,
|
|
5050
5050
|
ctx.signMessage,
|
|
5051
5051
|
ctx.embeddedWalletSigner
|
|
5052
5052
|
);
|
|
5053
|
-
return [id,
|
|
5053
|
+
return [id, stored2];
|
|
5054
5054
|
})
|
|
5055
5055
|
)
|
|
5056
5056
|
);
|
|
@@ -5068,18 +5068,18 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
5068
5068
|
})
|
|
5069
5069
|
);
|
|
5070
5070
|
return topK.map(({ message, similarity, chunkTextSource }) => {
|
|
5071
|
-
const
|
|
5071
|
+
const stored2 = { ...storedById.get(message.id) };
|
|
5072
5072
|
let chunkText2;
|
|
5073
5073
|
if (chunkTextSource.kind === "chunk") {
|
|
5074
|
-
chunkText2 = resolveChunkText(
|
|
5074
|
+
chunkText2 = resolveChunkText(stored2.content, chunkTextSource.chunk, chunkTextSource.siblings);
|
|
5075
5075
|
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
5076
5076
|
const state = chunkStateByMsgId.get(message.id);
|
|
5077
5077
|
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
5078
|
-
chunkText2 = resolveChunkText(
|
|
5078
|
+
chunkText2 = resolveChunkText(stored2.content, chunk, state?.chunks);
|
|
5079
5079
|
} else {
|
|
5080
|
-
chunkText2 =
|
|
5080
|
+
chunkText2 = stored2.content;
|
|
5081
5081
|
}
|
|
5082
|
-
return { chunkText: chunkText2, message:
|
|
5082
|
+
return { chunkText: chunkText2, message: stored2, similarity };
|
|
5083
5083
|
});
|
|
5084
5084
|
}
|
|
5085
5085
|
async function getAllFilesOp(ctx, options) {
|
|
@@ -5425,7 +5425,7 @@ async function embedOne(text12, options, outer) {
|
|
|
5425
5425
|
}
|
|
5426
5426
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
5427
5427
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
5428
|
-
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
|
|
5428
|
+
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs, outer) {
|
|
5429
5429
|
const response = await withEmbeddingRetry(
|
|
5430
5430
|
() => withDeadline(
|
|
5431
5431
|
(signal) => postApiV1Embeddings({
|
|
@@ -5435,8 +5435,10 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
5435
5435
|
...signal && { signal }
|
|
5436
5436
|
}),
|
|
5437
5437
|
timeoutMs,
|
|
5438
|
-
"embedding batch request"
|
|
5439
|
-
|
|
5438
|
+
"embedding batch request",
|
|
5439
|
+
outer
|
|
5440
|
+
),
|
|
5441
|
+
outer
|
|
5440
5442
|
);
|
|
5441
5443
|
if (response.error) {
|
|
5442
5444
|
throw embeddingErrorFrom(response);
|
|
@@ -5454,6 +5456,11 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
5454
5456
|
}
|
|
5455
5457
|
async function generateEmbeddings(texts, options) {
|
|
5456
5458
|
if (texts.length === 0) return [];
|
|
5459
|
+
const total = options.totalTimeoutMs;
|
|
5460
|
+
if (total === void 0) return embedMany(texts, options, void 0);
|
|
5461
|
+
return withDeadline((signal) => embedMany(texts, options, signal), total, "embedding batch");
|
|
5462
|
+
}
|
|
5463
|
+
async function embedMany(texts, options, outer) {
|
|
5457
5464
|
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
5458
5465
|
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
5459
5466
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
@@ -5474,7 +5481,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
5474
5481
|
if (uncachedTexts.length === 0) {
|
|
5475
5482
|
return results;
|
|
5476
5483
|
}
|
|
5477
|
-
const headers = await resolveAuthHeaders(options);
|
|
5484
|
+
const headers = await resolveAuthHeaders(options, outer);
|
|
5485
|
+
if (outer?.aborted) throw outer.reason;
|
|
5478
5486
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5479
5487
|
let newEmbeddings;
|
|
5480
5488
|
if (uncachedTexts.length <= chunkSize) {
|
|
@@ -5485,7 +5493,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
5485
5493
|
embeddingModel,
|
|
5486
5494
|
options.onUsage,
|
|
5487
5495
|
options.maskInput,
|
|
5488
|
-
timeoutMs
|
|
5496
|
+
timeoutMs,
|
|
5497
|
+
outer
|
|
5489
5498
|
);
|
|
5490
5499
|
} else {
|
|
5491
5500
|
const chunks = [];
|
|
@@ -5496,6 +5505,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
5496
5505
|
let nextIndex = 0;
|
|
5497
5506
|
const worker = async () => {
|
|
5498
5507
|
while (nextIndex < chunks.length) {
|
|
5508
|
+
if (outer?.aborted) throw outer.reason;
|
|
5499
5509
|
const idx = nextIndex++;
|
|
5500
5510
|
allEmbeddings[idx] = await generateEmbeddingsBatch(
|
|
5501
5511
|
chunks[idx],
|
|
@@ -5504,7 +5514,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
5504
5514
|
embeddingModel,
|
|
5505
5515
|
options.onUsage,
|
|
5506
5516
|
options.maskInput,
|
|
5507
|
-
timeoutMs
|
|
5517
|
+
timeoutMs,
|
|
5518
|
+
outer
|
|
5508
5519
|
);
|
|
5509
5520
|
}
|
|
5510
5521
|
};
|
|
@@ -5515,6 +5526,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
5515
5526
|
await Promise.all(workers);
|
|
5516
5527
|
newEmbeddings = allEmbeddings.flat();
|
|
5517
5528
|
}
|
|
5529
|
+
if (outer?.aborted) throw outer.reason;
|
|
5518
5530
|
for (let i = 0; i < uncachedIndices.length; i++) {
|
|
5519
5531
|
const f32Embedding = Float32Array.from(newEmbeddings[i]);
|
|
5520
5532
|
results[uncachedIndices[i]] = Array.from(f32Embedding);
|
|
@@ -10674,15 +10686,15 @@ function createSummaryContext(database) {
|
|
|
10674
10686
|
summariesCollection: database.get("conversation_summaries")
|
|
10675
10687
|
};
|
|
10676
10688
|
}
|
|
10677
|
-
function modelToStored(
|
|
10689
|
+
function modelToStored(record2) {
|
|
10678
10690
|
return {
|
|
10679
|
-
uniqueId:
|
|
10680
|
-
conversationId:
|
|
10681
|
-
summary:
|
|
10682
|
-
summarizedUpTo:
|
|
10683
|
-
tokenCount:
|
|
10684
|
-
createdAt:
|
|
10685
|
-
updatedAt:
|
|
10691
|
+
uniqueId: record2.id,
|
|
10692
|
+
conversationId: record2.conversationId,
|
|
10693
|
+
summary: record2.summary,
|
|
10694
|
+
summarizedUpTo: record2.summarizedUpTo,
|
|
10695
|
+
tokenCount: record2.tokenCount,
|
|
10696
|
+
createdAt: record2.createdAt,
|
|
10697
|
+
updatedAt: record2.updatedAt
|
|
10686
10698
|
};
|
|
10687
10699
|
}
|
|
10688
10700
|
async function getConversationSummaryOp(ctx, conversationId) {
|
|
@@ -10691,17 +10703,17 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
10691
10703
|
return modelToStored(results[0]);
|
|
10692
10704
|
}
|
|
10693
10705
|
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
10694
|
-
let
|
|
10706
|
+
let record2;
|
|
10695
10707
|
await ctx.database.write(async () => {
|
|
10696
10708
|
const existing = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
|
|
10697
10709
|
if (existing.length > 0) {
|
|
10698
|
-
|
|
10710
|
+
record2 = await existing[0].update((rec) => {
|
|
10699
10711
|
rec.summary = summary;
|
|
10700
10712
|
rec.summarizedUpTo = summarizedUpTo;
|
|
10701
10713
|
rec.tokenCount = tokenCount;
|
|
10702
10714
|
});
|
|
10703
10715
|
} else {
|
|
10704
|
-
|
|
10716
|
+
record2 = await ctx.summariesCollection.create((rec) => {
|
|
10705
10717
|
rec.conversationId = conversationId;
|
|
10706
10718
|
rec.summary = summary;
|
|
10707
10719
|
rec.summarizedUpTo = summarizedUpTo;
|
|
@@ -10709,13 +10721,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
|
|
|
10709
10721
|
});
|
|
10710
10722
|
}
|
|
10711
10723
|
});
|
|
10712
|
-
return modelToStored(
|
|
10724
|
+
return modelToStored(record2);
|
|
10713
10725
|
}
|
|
10714
10726
|
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
10715
10727
|
await ctx.database.write(async () => {
|
|
10716
10728
|
const existing = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
|
|
10717
|
-
for (const
|
|
10718
|
-
await
|
|
10729
|
+
for (const record2 of existing) {
|
|
10730
|
+
await record2.destroyPermanently();
|
|
10719
10731
|
}
|
|
10720
10732
|
});
|
|
10721
10733
|
}
|
|
@@ -10908,25 +10920,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
10908
10920
|
const kindBackfills = existing.filter((e) => {
|
|
10909
10921
|
const incoming = kindByName.get(e.canonicalName);
|
|
10910
10922
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
10911
|
-
}).map((
|
|
10923
|
+
}).map((record2) => ({ record: record2, kind: kindByName.get(record2.canonicalName) }));
|
|
10912
10924
|
const missing = unique.filter((n) => !existingNames.has(n));
|
|
10913
10925
|
const created = missing.map(
|
|
10914
|
-
(name) => ctx.entityCollection.prepareCreate((
|
|
10915
|
-
|
|
10926
|
+
(name) => ctx.entityCollection.prepareCreate((record2) => {
|
|
10927
|
+
record2._setRaw("canonical_name", name);
|
|
10916
10928
|
const kind = kindByName.get(name);
|
|
10917
|
-
if (kind !== void 0)
|
|
10929
|
+
if (kind !== void 0) record2._setRaw("kind", kind);
|
|
10918
10930
|
})
|
|
10919
10931
|
);
|
|
10920
10932
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
10921
|
-
for (const
|
|
10922
|
-
for (const { record, kind } of kindBackfills) {
|
|
10923
|
-
out.set(
|
|
10933
|
+
for (const record2 of created) out.set(record2.canonicalName, entityToStored(record2));
|
|
10934
|
+
for (const { record: record2, kind } of kindBackfills) {
|
|
10935
|
+
out.set(record2.canonicalName, { ...entityToStored(record2), kind });
|
|
10924
10936
|
}
|
|
10925
10937
|
return { entities: out, operations: created, kindBackfills };
|
|
10926
10938
|
}
|
|
10927
10939
|
function prepareKindBackfills(backfills) {
|
|
10928
10940
|
return backfills.map(
|
|
10929
|
-
({ record, kind }) =>
|
|
10941
|
+
({ record: record2, kind }) => record2.prepareUpdate((r) => {
|
|
10930
10942
|
r._setRaw("kind", kind);
|
|
10931
10943
|
})
|
|
10932
10944
|
);
|
|
@@ -10957,10 +10969,10 @@ function displayNamesOf(entities) {
|
|
|
10957
10969
|
}
|
|
10958
10970
|
return out;
|
|
10959
10971
|
}
|
|
10960
|
-
function topicsEqual(
|
|
10961
|
-
if (
|
|
10972
|
+
function topicsEqual(stored2, computed) {
|
|
10973
|
+
if (stored2 === null || stored2.length !== computed.length) return false;
|
|
10962
10974
|
const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
|
|
10963
|
-
const storedKeys =
|
|
10975
|
+
const storedKeys = stored2.map(key).sort();
|
|
10964
10976
|
const computedKeys = computed.map(key).sort();
|
|
10965
10977
|
return storedKeys.every((k, i) => k === computedKeys[i]);
|
|
10966
10978
|
}
|
|
@@ -11026,10 +11038,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
11026
11038
|
return;
|
|
11027
11039
|
}
|
|
11028
11040
|
const linkOps = toCreate.map(
|
|
11029
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
if (userId !== void 0)
|
|
11041
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
|
|
11042
|
+
record2._setRaw("memory_id", memoryId);
|
|
11043
|
+
record2._setRaw("entity_id", e.uniqueId);
|
|
11044
|
+
if (userId !== void 0) record2._setRaw("user_id", userId);
|
|
11033
11045
|
})
|
|
11034
11046
|
);
|
|
11035
11047
|
await ctx.database.batch(
|
|
@@ -11097,10 +11109,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
11097
11109
|
...entityOps,
|
|
11098
11110
|
...prepareKindBackfills(kindBackfills),
|
|
11099
11111
|
...toCreate.map(
|
|
11100
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
if (userId !== void 0)
|
|
11112
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
|
|
11113
|
+
record2._setRaw("memory_id", memoryId);
|
|
11114
|
+
record2._setRaw("entity_id", e.uniqueId);
|
|
11115
|
+
if (userId !== void 0) record2._setRaw("user_id", userId);
|
|
11104
11116
|
})
|
|
11105
11117
|
),
|
|
11106
11118
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
@@ -13172,13 +13184,13 @@ async function relinkMisclassifiedVideosOp(ctx, walletAddress) {
|
|
|
13172
13184
|
toRelink.push({ media, ext: mime.split("/")[1] || "mp4" });
|
|
13173
13185
|
continue;
|
|
13174
13186
|
}
|
|
13175
|
-
const
|
|
13187
|
+
const stored2 = await mediaToStored(
|
|
13176
13188
|
media,
|
|
13177
13189
|
ctx.walletAddress,
|
|
13178
13190
|
ctx.signMessage,
|
|
13179
13191
|
ctx.embeddedWalletSigner
|
|
13180
13192
|
);
|
|
13181
|
-
const ext = videoExtensionOf(
|
|
13193
|
+
const ext = videoExtensionOf(stored2.sourceUrl) ?? videoExtensionOf(stored2.name);
|
|
13182
13194
|
if (ext) {
|
|
13183
13195
|
toRelink.push({ media, ext });
|
|
13184
13196
|
}
|
|
@@ -13474,8 +13486,8 @@ function visibilityConditions(requested) {
|
|
|
13474
13486
|
if (excluded.length === 0) return [];
|
|
13475
13487
|
return [Q8.or(Q8.where("visibility", null), Q8.where("visibility", Q8.notIn(excluded)))];
|
|
13476
13488
|
}
|
|
13477
|
-
function isOwnedByCtxUser(ctx,
|
|
13478
|
-
return ctx.userId === void 0 ||
|
|
13489
|
+
function isOwnedByCtxUser(ctx, record2) {
|
|
13490
|
+
return ctx.userId === void 0 || record2.userId === ctx.userId;
|
|
13479
13491
|
}
|
|
13480
13492
|
function baseVaultConditions(ctx, options) {
|
|
13481
13493
|
return [
|
|
@@ -13555,39 +13567,39 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
13555
13567
|
}
|
|
13556
13568
|
return raw;
|
|
13557
13569
|
}
|
|
13558
|
-
function populateNewVaultMemory(
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13563
|
-
|
|
13570
|
+
function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
|
|
13571
|
+
record2._setRaw("content", encryptedContent);
|
|
13572
|
+
record2._setRaw("scope", opts.scope ?? "private");
|
|
13573
|
+
record2._setRaw("folder_id", opts.folderId ?? null);
|
|
13574
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
13575
|
+
record2._setRaw("is_deleted", false);
|
|
13564
13576
|
if (opts.embedding !== void 0) {
|
|
13565
|
-
|
|
13566
|
-
|
|
13577
|
+
record2._setRaw("embedding", opts.embedding);
|
|
13578
|
+
record2._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
13567
13579
|
}
|
|
13568
13580
|
if (opts.sourceChunkIds !== void 0) {
|
|
13569
|
-
|
|
13581
|
+
record2._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
|
|
13570
13582
|
}
|
|
13571
|
-
|
|
13572
|
-
|
|
13583
|
+
record2._setRaw("proof_count", opts.proofCount ?? 1);
|
|
13584
|
+
record2._setRaw("source", opts.source ?? "manual");
|
|
13573
13585
|
if (opts.eventTime) {
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13586
|
+
record2._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
13587
|
+
record2._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
13588
|
+
record2._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
13577
13589
|
}
|
|
13578
13590
|
if (opts.factType !== void 0) {
|
|
13579
|
-
|
|
13591
|
+
record2._setRaw("fact_type", opts.factType);
|
|
13580
13592
|
}
|
|
13581
13593
|
if (opts.trustTier !== void 0) {
|
|
13582
|
-
|
|
13594
|
+
record2._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
13583
13595
|
}
|
|
13584
|
-
|
|
13585
|
-
|
|
13596
|
+
record2._setRaw("visibility", opts.visibility ?? "private");
|
|
13597
|
+
record2._setRaw(
|
|
13586
13598
|
"published_at",
|
|
13587
13599
|
opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
|
|
13588
13600
|
);
|
|
13589
13601
|
if (opts.geohash !== void 0) {
|
|
13590
|
-
|
|
13602
|
+
record2._setRaw("geohash", opts.geohash);
|
|
13591
13603
|
}
|
|
13592
13604
|
}
|
|
13593
13605
|
async function createVaultMemoryOp(ctx, opts) {
|
|
@@ -13601,7 +13613,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
13601
13613
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
13602
13614
|
throw new Error("Memory source is no longer eligible");
|
|
13603
13615
|
return ctx.vaultMemoryCollection.create(
|
|
13604
|
-
(
|
|
13616
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
13605
13617
|
);
|
|
13606
13618
|
});
|
|
13607
13619
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -13626,7 +13638,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
13626
13638
|
}
|
|
13627
13639
|
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
|
|
13628
13640
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
13629
|
-
(
|
|
13641
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
13630
13642
|
);
|
|
13631
13643
|
await target.update((r) => {
|
|
13632
13644
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -13708,7 +13720,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13708
13720
|
throw new Error("Memory source is no longer eligible");
|
|
13709
13721
|
const prepared = optionsArray.map(
|
|
13710
13722
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
13711
|
-
(
|
|
13723
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
|
|
13712
13724
|
)
|
|
13713
13725
|
);
|
|
13714
13726
|
await ctx.database.batch(...prepared);
|
|
@@ -13716,16 +13728,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13716
13728
|
});
|
|
13717
13729
|
return Promise.all(
|
|
13718
13730
|
created.map(
|
|
13719
|
-
(
|
|
13731
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
13720
13732
|
)
|
|
13721
13733
|
);
|
|
13722
13734
|
}
|
|
13723
13735
|
async function getVaultMemoryOp(ctx, id) {
|
|
13724
13736
|
try {
|
|
13725
|
-
const
|
|
13726
|
-
if (
|
|
13737
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
13738
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
13727
13739
|
return vaultMemoryToStored(
|
|
13728
|
-
|
|
13740
|
+
record2,
|
|
13729
13741
|
ctx.walletAddress,
|
|
13730
13742
|
ctx.signMessage,
|
|
13731
13743
|
ctx.embeddedWalletSigner
|
|
@@ -13783,11 +13795,11 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
13783
13795
|
};
|
|
13784
13796
|
}
|
|
13785
13797
|
async function vaultMemoryRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner) {
|
|
13786
|
-
const
|
|
13798
|
+
const stored2 = vaultMemoryRawToStoredRaw(raw);
|
|
13787
13799
|
if (walletAddress) {
|
|
13788
|
-
return decryptVaultMemoryFields(
|
|
13800
|
+
return decryptVaultMemoryFields(stored2, walletAddress, signMessage, embeddedWalletSigner);
|
|
13789
13801
|
}
|
|
13790
|
-
return
|
|
13802
|
+
return stored2;
|
|
13791
13803
|
}
|
|
13792
13804
|
async function getAllVaultMemoriesOp(ctx, options) {
|
|
13793
13805
|
const conditions = [
|
|
@@ -13939,13 +13951,13 @@ async function getVaultMemoriesByIdsOp(ctx, ids, options) {
|
|
|
13939
13951
|
async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
13940
13952
|
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
|
|
13941
13953
|
return mapInBatches(results, async (raw) => {
|
|
13942
|
-
const
|
|
13954
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
13943
13955
|
raw,
|
|
13944
13956
|
ctx.walletAddress,
|
|
13945
13957
|
ctx.signMessage,
|
|
13946
13958
|
ctx.embeddedWalletSigner
|
|
13947
13959
|
);
|
|
13948
|
-
return
|
|
13960
|
+
return stored2.content;
|
|
13949
13961
|
});
|
|
13950
13962
|
}
|
|
13951
13963
|
async function countActiveVaultMemoriesOp(ctx) {
|
|
@@ -13967,12 +13979,12 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13967
13979
|
ctx.embeddedWalletSigner
|
|
13968
13980
|
) : opts.content;
|
|
13969
13981
|
let stale = false;
|
|
13970
|
-
const
|
|
13971
|
-
const originalUpdatedAt =
|
|
13982
|
+
const record2 = probe;
|
|
13983
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13972
13984
|
await ctx.database.write(async () => {
|
|
13973
13985
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
13974
13986
|
throw new Error("Memory source is no longer eligible");
|
|
13975
|
-
if (
|
|
13987
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
13976
13988
|
stale = true;
|
|
13977
13989
|
return;
|
|
13978
13990
|
}
|
|
@@ -13980,14 +13992,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13980
13992
|
let replayedObservation = false;
|
|
13981
13993
|
if (opts.observationSourceIds?.length) {
|
|
13982
13994
|
try {
|
|
13983
|
-
const parsed = JSON.parse(
|
|
13995
|
+
const parsed = JSON.parse(record2.sourceChunkIds ?? "[]");
|
|
13984
13996
|
if (Array.isArray(parsed))
|
|
13985
13997
|
observedSources = parsed.filter((id2) => typeof id2 === "string");
|
|
13986
13998
|
} catch {
|
|
13987
13999
|
}
|
|
13988
14000
|
replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
|
|
13989
14001
|
}
|
|
13990
|
-
await
|
|
14002
|
+
await record2.update((r) => {
|
|
13991
14003
|
r._setRaw("content", encryptedContent);
|
|
13992
14004
|
if (opts.scope !== void 0) {
|
|
13993
14005
|
r._setRaw("scope", opts.scope);
|
|
@@ -14044,7 +14056,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
14044
14056
|
});
|
|
14045
14057
|
if (stale) return null;
|
|
14046
14058
|
return vaultMemoryToStored(
|
|
14047
|
-
|
|
14059
|
+
record2,
|
|
14048
14060
|
ctx.walletAddress,
|
|
14049
14061
|
ctx.signMessage,
|
|
14050
14062
|
ctx.embeddedWalletSigner
|
|
@@ -14058,21 +14070,21 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
14058
14070
|
if (!entityCtx) {
|
|
14059
14071
|
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
14060
14072
|
}
|
|
14061
|
-
let
|
|
14073
|
+
let record2;
|
|
14062
14074
|
try {
|
|
14063
|
-
|
|
14075
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
14064
14076
|
} catch {
|
|
14065
14077
|
return null;
|
|
14066
14078
|
}
|
|
14067
|
-
if (
|
|
14079
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
14068
14080
|
let stale = false;
|
|
14069
|
-
const originalUpdatedAt =
|
|
14081
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14070
14082
|
await ctx.database.write(async (writer) => {
|
|
14071
|
-
if (
|
|
14083
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14072
14084
|
stale = true;
|
|
14073
14085
|
return;
|
|
14074
14086
|
}
|
|
14075
|
-
await
|
|
14087
|
+
await record2.update((r) => {
|
|
14076
14088
|
r._setRaw("topics_user_managed", true);
|
|
14077
14089
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
14078
14090
|
});
|
|
@@ -14096,25 +14108,25 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
14096
14108
|
);
|
|
14097
14109
|
});
|
|
14098
14110
|
if (stale) return null;
|
|
14099
|
-
return vaultMemoryToStored(
|
|
14111
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
14100
14112
|
}
|
|
14101
14113
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
14102
|
-
let
|
|
14114
|
+
let record2;
|
|
14103
14115
|
try {
|
|
14104
|
-
|
|
14116
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
14105
14117
|
} catch {
|
|
14106
14118
|
return false;
|
|
14107
14119
|
}
|
|
14108
|
-
if (
|
|
14109
|
-
const originalUpdatedAt =
|
|
14120
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14121
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14110
14122
|
let cleared = false;
|
|
14111
14123
|
await ctx.database.write(async () => {
|
|
14112
|
-
if (options?.unlessTopicsRecorded && parseTopics(
|
|
14124
|
+
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
14113
14125
|
cleared = true;
|
|
14114
|
-
await
|
|
14126
|
+
await record2.update((r) => {
|
|
14115
14127
|
r._setRaw("topics_user_managed", false);
|
|
14116
14128
|
r._setRaw("topics_extracted_version", null);
|
|
14117
|
-
if (
|
|
14129
|
+
if (record2.topicsExtractedAt === null) {
|
|
14118
14130
|
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
14119
14131
|
}
|
|
14120
14132
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -14123,22 +14135,22 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
14123
14135
|
return cleared;
|
|
14124
14136
|
}
|
|
14125
14137
|
async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
14126
|
-
let
|
|
14138
|
+
let record2;
|
|
14127
14139
|
try {
|
|
14128
|
-
|
|
14140
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14129
14141
|
} catch {
|
|
14130
14142
|
return null;
|
|
14131
14143
|
}
|
|
14132
|
-
if (
|
|
14144
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
14133
14145
|
let stale = false;
|
|
14134
14146
|
await ctx.database.write(async () => {
|
|
14135
|
-
if (
|
|
14147
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14136
14148
|
stale = true;
|
|
14137
14149
|
return;
|
|
14138
14150
|
}
|
|
14139
|
-
const currentUpdatedAt =
|
|
14140
|
-
const currentPublishedAt =
|
|
14141
|
-
await
|
|
14151
|
+
const currentUpdatedAt = record2.updatedAt.getTime();
|
|
14152
|
+
const currentPublishedAt = record2.publishedAt ?? null;
|
|
14153
|
+
await record2.update((r) => {
|
|
14142
14154
|
r._setRaw("visibility", opts.visibility);
|
|
14143
14155
|
if (opts.visibility === "private") {
|
|
14144
14156
|
r._setRaw("published_at", null);
|
|
@@ -14152,19 +14164,19 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
14152
14164
|
});
|
|
14153
14165
|
});
|
|
14154
14166
|
if (stale) return null;
|
|
14155
|
-
return vaultMemoryToStored(
|
|
14167
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
14156
14168
|
}
|
|
14157
14169
|
async function deleteVaultMemoryOp(ctx, id) {
|
|
14158
14170
|
try {
|
|
14159
|
-
const
|
|
14160
|
-
if (
|
|
14171
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14172
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14161
14173
|
let stale = false;
|
|
14162
14174
|
await ctx.database.write(async () => {
|
|
14163
|
-
if (
|
|
14175
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14164
14176
|
stale = true;
|
|
14165
14177
|
return;
|
|
14166
14178
|
}
|
|
14167
|
-
await
|
|
14179
|
+
await record2.update((r) => {
|
|
14168
14180
|
r._setRaw("is_deleted", true);
|
|
14169
14181
|
});
|
|
14170
14182
|
});
|
|
@@ -14183,8 +14195,8 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
14183
14195
|
async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
14184
14196
|
if (id === supersededById) return false;
|
|
14185
14197
|
try {
|
|
14186
|
-
const
|
|
14187
|
-
if (
|
|
14198
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14199
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14188
14200
|
let successor;
|
|
14189
14201
|
try {
|
|
14190
14202
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -14198,7 +14210,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
14198
14210
|
await ctx.database.write(async () => {
|
|
14199
14211
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
14200
14212
|
throw new Error("Memory source is no longer eligible");
|
|
14201
|
-
if (
|
|
14213
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
14202
14214
|
stale = true;
|
|
14203
14215
|
return;
|
|
14204
14216
|
}
|
|
@@ -14206,7 +14218,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
14206
14218
|
stale = true;
|
|
14207
14219
|
return;
|
|
14208
14220
|
}
|
|
14209
|
-
await
|
|
14221
|
+
await record2.update((r) => {
|
|
14210
14222
|
r._setRaw("superseded_by", supersededById);
|
|
14211
14223
|
r._setRaw("superseded_at", Date.now());
|
|
14212
14224
|
});
|
|
@@ -14225,7 +14237,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
14225
14237
|
const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
|
|
14226
14238
|
return mapInBatches(
|
|
14227
14239
|
results,
|
|
14228
|
-
(
|
|
14240
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
14229
14241
|
);
|
|
14230
14242
|
}
|
|
14231
14243
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
@@ -14367,17 +14379,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
14367
14379
|
}
|
|
14368
14380
|
}
|
|
14369
14381
|
const eligible = records.filter(
|
|
14370
|
-
(
|
|
14382
|
+
(record2) => !record2.isDeleted && isOwnedByCtxUser(ctx, record2) && !record2.topicsUserManaged
|
|
14371
14383
|
);
|
|
14372
|
-
const prepared = eligible.map((
|
|
14373
|
-
const originalUpdatedAt =
|
|
14374
|
-
return
|
|
14384
|
+
const prepared = eligible.map((record2) => {
|
|
14385
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14386
|
+
return record2.prepareUpdate((r) => {
|
|
14375
14387
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
14376
14388
|
r._setRaw("topics_extracted_version", version);
|
|
14377
14389
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
14378
14390
|
});
|
|
14379
14391
|
});
|
|
14380
|
-
for (const
|
|
14392
|
+
for (const record2 of eligible) stamped.push(record2.id);
|
|
14381
14393
|
if (prepared.length > 0) await ctx.database.batch(...prepared);
|
|
14382
14394
|
});
|
|
14383
14395
|
}
|
|
@@ -14392,14 +14404,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14392
14404
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
14393
14405
|
try {
|
|
14394
14406
|
await ctx.database.write(async (writer) => {
|
|
14395
|
-
let
|
|
14407
|
+
let record2;
|
|
14396
14408
|
try {
|
|
14397
|
-
|
|
14409
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14398
14410
|
} catch {
|
|
14399
14411
|
return;
|
|
14400
14412
|
}
|
|
14401
|
-
if (
|
|
14402
|
-
const topics = parseTopics(
|
|
14413
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14414
|
+
const topics = parseTopics(record2.topics);
|
|
14403
14415
|
if (topics === null) return;
|
|
14404
14416
|
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
|
|
14405
14417
|
relinked.push(id);
|
|
@@ -14424,20 +14436,20 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14424
14436
|
await ctx.database.write(async () => {
|
|
14425
14437
|
const writes = [];
|
|
14426
14438
|
for (const id of chunkIds) {
|
|
14427
|
-
let
|
|
14439
|
+
let record2;
|
|
14428
14440
|
try {
|
|
14429
|
-
|
|
14441
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14430
14442
|
} catch {
|
|
14431
14443
|
continue;
|
|
14432
14444
|
}
|
|
14433
|
-
if (
|
|
14434
|
-
if (parseTopics(
|
|
14445
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) continue;
|
|
14446
|
+
if (parseTopics(record2.topics) !== null) continue;
|
|
14435
14447
|
const links = await entityCtx.memoryEntityCollection.query(Q8.where("memory_id", id)).unsafeFetchRaw();
|
|
14436
14448
|
const entityIds = links.map((l) => String(l.entity_id));
|
|
14437
14449
|
if (entityIds.length === 0) continue;
|
|
14438
14450
|
const entities = await entityCtx.entityCollection.query(Q8.where("id", Q8.oneOf(entityIds))).fetch();
|
|
14439
14451
|
if (entities.length === 0) continue;
|
|
14440
|
-
const source =
|
|
14452
|
+
const source = record2.topicsUserManaged ? "user" : "auto";
|
|
14441
14453
|
const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
|
|
14442
14454
|
if (write) writes.push(write);
|
|
14443
14455
|
}
|
|
@@ -14455,7 +14467,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
14455
14467
|
if (records.length === 0) return 0;
|
|
14456
14468
|
await ctx.database.write(async () => {
|
|
14457
14469
|
const prepared = records.map(
|
|
14458
|
-
(
|
|
14470
|
+
(record2) => record2.prepareUpdate((r) => {
|
|
14459
14471
|
r._setRaw("is_deleted", true);
|
|
14460
14472
|
})
|
|
14461
14473
|
);
|
|
@@ -14500,20 +14512,20 @@ async function getDecayCandidatesRawOp(ctx) {
|
|
|
14500
14512
|
}
|
|
14501
14513
|
async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
14502
14514
|
try {
|
|
14503
|
-
const
|
|
14504
|
-
if (
|
|
14515
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14516
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14505
14517
|
let stale = false;
|
|
14506
14518
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
14507
14519
|
await ctx.database.write(async () => {
|
|
14508
|
-
if (
|
|
14520
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
14509
14521
|
stale = true;
|
|
14510
14522
|
return;
|
|
14511
14523
|
}
|
|
14512
|
-
if (opts?.expectedUpdatedAt !== void 0 &&
|
|
14524
|
+
if (opts?.expectedUpdatedAt !== void 0 && record2.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record2.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
|
|
14513
14525
|
stale = true;
|
|
14514
14526
|
return;
|
|
14515
14527
|
}
|
|
14516
|
-
await
|
|
14528
|
+
await record2.update((r) => {
|
|
14517
14529
|
r._setRaw("archived_at", archivedAtValue);
|
|
14518
14530
|
});
|
|
14519
14531
|
});
|
|
@@ -14524,15 +14536,15 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
14524
14536
|
}
|
|
14525
14537
|
async function restoreVaultMemoryOp(ctx, id) {
|
|
14526
14538
|
try {
|
|
14527
|
-
const
|
|
14528
|
-
if (
|
|
14539
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14540
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14529
14541
|
let stale = false;
|
|
14530
14542
|
await ctx.database.write(async () => {
|
|
14531
|
-
if (
|
|
14543
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14532
14544
|
stale = true;
|
|
14533
14545
|
return;
|
|
14534
14546
|
}
|
|
14535
|
-
await
|
|
14547
|
+
await record2.update((r) => {
|
|
14536
14548
|
r._setRaw("archived_at", null);
|
|
14537
14549
|
});
|
|
14538
14550
|
});
|
|
@@ -14543,17 +14555,17 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
14543
14555
|
}
|
|
14544
14556
|
async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
14545
14557
|
try {
|
|
14546
|
-
const
|
|
14547
|
-
if (
|
|
14558
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14559
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14548
14560
|
const now = opts.now ?? Date.now();
|
|
14549
14561
|
let stale = false;
|
|
14550
14562
|
await ctx.database.write(async () => {
|
|
14551
|
-
const archivedAt =
|
|
14552
|
-
if (
|
|
14563
|
+
const archivedAt = record2.archivedAt;
|
|
14564
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
14553
14565
|
stale = true;
|
|
14554
14566
|
return;
|
|
14555
14567
|
}
|
|
14556
|
-
await
|
|
14568
|
+
await record2.update((r) => {
|
|
14557
14569
|
r._setRaw("is_deleted", true);
|
|
14558
14570
|
});
|
|
14559
14571
|
});
|
|
@@ -14571,14 +14583,14 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
14571
14583
|
}
|
|
14572
14584
|
async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel, expected) {
|
|
14573
14585
|
try {
|
|
14574
|
-
const
|
|
14575
|
-
if (
|
|
14576
|
-
const readUpdatedAt =
|
|
14577
|
-
const readStoredContent =
|
|
14586
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14587
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14588
|
+
const readUpdatedAt = record2.updatedAt.getTime();
|
|
14589
|
+
const readStoredContent = record2._getRaw("content");
|
|
14578
14590
|
if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
|
|
14579
14591
|
if (expected?.content !== void 0) {
|
|
14580
14592
|
const current = await vaultMemoryToStored(
|
|
14581
|
-
|
|
14593
|
+
record2,
|
|
14582
14594
|
ctx.walletAddress,
|
|
14583
14595
|
ctx.signMessage,
|
|
14584
14596
|
ctx.embeddedWalletSigner
|
|
@@ -14587,11 +14599,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
14587
14599
|
}
|
|
14588
14600
|
let written = false;
|
|
14589
14601
|
await ctx.database.write(async () => {
|
|
14590
|
-
if (
|
|
14591
|
-
const originalUpdatedAt =
|
|
14592
|
-
if (originalUpdatedAt !== readUpdatedAt ||
|
|
14602
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14603
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14604
|
+
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
14593
14605
|
return;
|
|
14594
|
-
await
|
|
14606
|
+
await record2.update((r) => {
|
|
14595
14607
|
r._setRaw("embedding", embedding);
|
|
14596
14608
|
r._setRaw("embedding_model", embeddingModel);
|
|
14597
14609
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -14606,8 +14618,8 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
14606
14618
|
function normalizeForDedupe(content) {
|
|
14607
14619
|
return content.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
14608
14620
|
}
|
|
14609
|
-
async function findQuarantinedDuplicateOp(ctx, content,
|
|
14610
|
-
const wanted = [...new Set(
|
|
14621
|
+
async function findQuarantinedDuplicateOp(ctx, content, sourceIds2, where) {
|
|
14622
|
+
const wanted = [...new Set(sourceIds2)].sort().join("\0");
|
|
14611
14623
|
const target = normalizeForDedupe(content);
|
|
14612
14624
|
const rows = await ctx.vaultMemoryCollection.query(
|
|
14613
14625
|
Q8.where("trust_tier", "quarantined"),
|
|
@@ -14626,13 +14638,13 @@ async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
|
|
|
14626
14638
|
if (!Array.isArray(ids)) continue;
|
|
14627
14639
|
const key = [...new Set(ids.filter((id) => typeof id === "string"))].sort().join("\0");
|
|
14628
14640
|
if (key !== wanted) continue;
|
|
14629
|
-
const
|
|
14641
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
14630
14642
|
raw,
|
|
14631
14643
|
ctx.walletAddress,
|
|
14632
14644
|
ctx.signMessage,
|
|
14633
14645
|
ctx.embeddedWalletSigner
|
|
14634
14646
|
);
|
|
14635
|
-
if (normalizeForDedupe(
|
|
14647
|
+
if (normalizeForDedupe(stored2.content) === target) return stored2.uniqueId;
|
|
14636
14648
|
}
|
|
14637
14649
|
return null;
|
|
14638
14650
|
}
|
|
@@ -14741,25 +14753,25 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
14741
14753
|
inserted = writable.length;
|
|
14742
14754
|
if (writable.length === 0) return;
|
|
14743
14755
|
const prepared = writable.map(
|
|
14744
|
-
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((
|
|
14745
|
-
|
|
14746
|
-
|
|
14747
|
-
|
|
14748
|
-
|
|
14749
|
-
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14756
|
+
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record2) => {
|
|
14757
|
+
record2._raw.id = row.memoryId;
|
|
14758
|
+
record2._setRaw("content", content);
|
|
14759
|
+
record2._setRaw("scope", "shared");
|
|
14760
|
+
record2._setRaw("folder_id", null);
|
|
14761
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
14762
|
+
record2._setRaw("is_deleted", false);
|
|
14763
|
+
record2._setRaw("proof_count", 1);
|
|
14764
|
+
record2._setRaw("source", SOURCE_PHOTO);
|
|
14765
|
+
record2._setRaw(
|
|
14754
14766
|
"media",
|
|
14755
14767
|
row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
|
|
14756
14768
|
);
|
|
14757
|
-
|
|
14758
|
-
|
|
14769
|
+
record2._setRaw("visibility", "public");
|
|
14770
|
+
record2._setRaw("published_at", now);
|
|
14759
14771
|
if (row.eventTime) {
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14772
|
+
record2._setRaw("event_time_start", row.eventTime.start ?? null);
|
|
14773
|
+
record2._setRaw("event_time_end", row.eventTime.end ?? null);
|
|
14774
|
+
record2._setRaw("event_time_kind", row.eventTime.kind ?? null);
|
|
14763
14775
|
}
|
|
14764
14776
|
})
|
|
14765
14777
|
);
|
|
@@ -15580,11 +15592,11 @@ function folderToStored(folder) {
|
|
|
15580
15592
|
}
|
|
15581
15593
|
async function createVaultFolderOp(ctx, opts) {
|
|
15582
15594
|
const created = await ctx.database.write(async () => {
|
|
15583
|
-
return ctx.vaultFolderCollection.create((
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15595
|
+
return ctx.vaultFolderCollection.create((record2) => {
|
|
15596
|
+
record2._setRaw("name", opts.name);
|
|
15597
|
+
record2._setRaw("scope", opts.scope ?? "private");
|
|
15598
|
+
record2._setRaw("is_system", opts.isSystem ?? false);
|
|
15599
|
+
record2._setRaw("is_deleted", false);
|
|
15588
15600
|
});
|
|
15589
15601
|
});
|
|
15590
15602
|
return folderToStored(created);
|
|
@@ -15595,14 +15607,14 @@ async function getAllVaultFoldersOp(ctx) {
|
|
|
15595
15607
|
}
|
|
15596
15608
|
async function updateVaultFolderOp(ctx, id, opts) {
|
|
15597
15609
|
try {
|
|
15598
|
-
const
|
|
15599
|
-
if (
|
|
15600
|
-
const scopeChanged = opts.scope !== void 0 && opts.scope !==
|
|
15610
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
15611
|
+
if (record2.isDeleted) return null;
|
|
15612
|
+
const scopeChanged = opts.scope !== void 0 && opts.scope !== record2.scope;
|
|
15601
15613
|
const updated = await ctx.database.write(async () => {
|
|
15602
15614
|
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q13.where("folder_id", id), Q13.where("is_deleted", false)).fetch() : [];
|
|
15603
15615
|
const updates = [];
|
|
15604
15616
|
updates.push(
|
|
15605
|
-
|
|
15617
|
+
record2.prepareUpdate((r) => {
|
|
15606
15618
|
if (opts.name !== void 0) r._setRaw("name", opts.name);
|
|
15607
15619
|
if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
|
|
15608
15620
|
})
|
|
@@ -15624,8 +15636,8 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
15624
15636
|
}
|
|
15625
15637
|
async function deleteVaultFolderOp(ctx, id) {
|
|
15626
15638
|
try {
|
|
15627
|
-
const
|
|
15628
|
-
if (
|
|
15639
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
15640
|
+
if (record2.isDeleted) return false;
|
|
15629
15641
|
await ctx.database.write(async () => {
|
|
15630
15642
|
const memories = await ctx.vaultMemoryCollection.query(Q13.where("folder_id", id), Q13.where("is_deleted", false)).fetch();
|
|
15631
15643
|
const preparedMemories = memories.map(
|
|
@@ -15634,7 +15646,7 @@ async function deleteVaultFolderOp(ctx, id) {
|
|
|
15634
15646
|
r._setRaw("scope", "private");
|
|
15635
15647
|
})
|
|
15636
15648
|
);
|
|
15637
|
-
const preparedFolder =
|
|
15649
|
+
const preparedFolder = record2.prepareUpdate((r) => {
|
|
15638
15650
|
r._setRaw("is_deleted", true);
|
|
15639
15651
|
});
|
|
15640
15652
|
await ctx.database.batch(...preparedMemories, preparedFolder);
|
|
@@ -15680,11 +15692,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
15680
15692
|
}
|
|
15681
15693
|
async function updateVaultFolderContextOp(ctx, id, context) {
|
|
15682
15694
|
try {
|
|
15683
|
-
const
|
|
15684
|
-
if (
|
|
15695
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
15696
|
+
if (record2.isDeleted) return null;
|
|
15685
15697
|
const updated = await ctx.database.write(async () => {
|
|
15686
15698
|
await ctx.database.batch(
|
|
15687
|
-
|
|
15699
|
+
record2.prepareUpdate((r) => {
|
|
15688
15700
|
r._setRaw("context", context);
|
|
15689
15701
|
})
|
|
15690
15702
|
);
|
|
@@ -17741,7 +17753,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
17741
17753
|
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
17742
17754
|
let subEmbeddings;
|
|
17743
17755
|
try {
|
|
17744
|
-
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
17756
|
+
subEmbeddings = prepared.facetEmbeddings ?? await generateEmbeddings(facetQueries, embeddingOptions);
|
|
17745
17757
|
} catch (err) {
|
|
17746
17758
|
getLogger().warn(
|
|
17747
17759
|
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
@@ -17926,6 +17938,35 @@ var DEFAULT_SCOPE = "private";
|
|
|
17926
17938
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
17927
17939
|
var DEFAULT_CONSOLIDATE_TOP_K = 20;
|
|
17928
17940
|
async function retain(content, ctx, options = {}) {
|
|
17941
|
+
return retainWithPersistence(
|
|
17942
|
+
content,
|
|
17943
|
+
{
|
|
17944
|
+
embeddingOptions: ctx.embeddingOptions,
|
|
17945
|
+
vaultCache: ctx.vaultCache,
|
|
17946
|
+
persistence: {
|
|
17947
|
+
prepare: (query, searchOptions) => prepareVaultCandidates(
|
|
17948
|
+
query,
|
|
17949
|
+
ctx.vaultCtx,
|
|
17950
|
+
ctx.embeddingOptions,
|
|
17951
|
+
ctx.vaultCache,
|
|
17952
|
+
searchOptions
|
|
17953
|
+
),
|
|
17954
|
+
get: (id) => getVaultMemoryOp(ctx.vaultCtx, id),
|
|
17955
|
+
tombstones: (_embedding, _model, scope, folderId) => getAllVaultMemoriesOp(ctx.vaultCtx, {
|
|
17956
|
+
includeDeleted: true,
|
|
17957
|
+
scopes: [scope],
|
|
17958
|
+
...folderId !== void 0 && { folderId }
|
|
17959
|
+
}),
|
|
17960
|
+
create: (input) => createVaultMemoryOp(ctx.vaultCtx, input),
|
|
17961
|
+
update: (id, patch) => updateVaultMemoryOp(ctx.vaultCtx, id, patch),
|
|
17962
|
+
supersede: (id, successor) => supersedeVaultMemoryOp(ctx.vaultCtx, id, successor),
|
|
17963
|
+
createSuperseding: (input, target) => createSupersedingMemoryOp(ctx.vaultCtx, input, target)
|
|
17964
|
+
}
|
|
17965
|
+
},
|
|
17966
|
+
options
|
|
17967
|
+
);
|
|
17968
|
+
}
|
|
17969
|
+
async function retainWithPersistence(content, ctx, options = {}) {
|
|
17929
17970
|
const trimmed = content.trim();
|
|
17930
17971
|
if (trimmed.length === 0) {
|
|
17931
17972
|
throw new Error("retain: content cannot be empty");
|
|
@@ -17938,19 +17979,13 @@ async function retain(content, ctx, options = {}) {
|
|
|
17938
17979
|
let supersedeContent;
|
|
17939
17980
|
let prepared;
|
|
17940
17981
|
if (enableAutoMerge) {
|
|
17941
|
-
prepared = await
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
{
|
|
17947
|
-
|
|
17948
|
-
useFusion: false,
|
|
17949
|
-
scopes: [resolvedScope],
|
|
17950
|
-
includeArchived: true,
|
|
17951
|
-
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
17952
|
-
}
|
|
17953
|
-
);
|
|
17982
|
+
prepared = await ctx.persistence.prepare(trimmed, {
|
|
17983
|
+
limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
|
|
17984
|
+
useFusion: false,
|
|
17985
|
+
scopes: [resolvedScope],
|
|
17986
|
+
includeArchived: true,
|
|
17987
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
17988
|
+
});
|
|
17954
17989
|
if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
|
|
17955
17990
|
throw new Error(
|
|
17956
17991
|
"retain: embeddings unavailable \u2014 refusing to auto-merge against an inert cosine lane, which would create a duplicate instead of merging into the existing memory. Retry when embeddings recover, or pass enableAutoMerge: false to force a create."
|
|
@@ -17981,7 +18016,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
17981
18016
|
);
|
|
17982
18017
|
if (matches.length > 0) {
|
|
17983
18018
|
const targetId = matches[0].uniqueId;
|
|
17984
|
-
const existing = await
|
|
18019
|
+
const existing = await ctx.persistence.get(targetId);
|
|
17985
18020
|
if (existing && !existing.supersededBy) {
|
|
17986
18021
|
const mergedSourceIds = unionStrings(
|
|
17987
18022
|
existing.sourceChunkIds ?? [],
|
|
@@ -17990,7 +18025,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
17990
18025
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
17991
18026
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
17992
18027
|
const resurrect = resurrectFields(existing);
|
|
17993
|
-
const updated = await
|
|
18028
|
+
const updated = await ctx.persistence.update(targetId, {
|
|
17994
18029
|
content: existing.content,
|
|
17995
18030
|
proofCountIncrement: 1,
|
|
17996
18031
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -18017,7 +18052,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
18017
18052
|
}
|
|
18018
18053
|
const contentToWrite = supersedeContent ?? trimmed;
|
|
18019
18054
|
const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
|
|
18020
|
-
const
|
|
18055
|
+
const generatedEmbedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
18056
|
+
const embedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
18021
18057
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18022
18058
|
if (options.respectTombstones) {
|
|
18023
18059
|
const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
@@ -18057,8 +18093,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
18057
18093
|
};
|
|
18058
18094
|
if (supersedeTargetIds.length > 0) {
|
|
18059
18095
|
const [primaryTargetId, ...restTargetIds] = supersedeTargetIds;
|
|
18060
|
-
const { created: created2, retired } = await
|
|
18061
|
-
ctx.vaultCtx,
|
|
18096
|
+
const { created: created2, retired } = await ctx.persistence.createSuperseding(
|
|
18062
18097
|
createOpts,
|
|
18063
18098
|
primaryTargetId
|
|
18064
18099
|
);
|
|
@@ -18074,11 +18109,11 @@ async function retain(content, ctx, options = {}) {
|
|
|
18074
18109
|
for (const staleId of restTargetIds) {
|
|
18075
18110
|
let ok = false;
|
|
18076
18111
|
try {
|
|
18077
|
-
ok = await
|
|
18112
|
+
ok = await ctx.persistence.supersede(staleId, created2.uniqueId) === true;
|
|
18078
18113
|
} catch {
|
|
18079
18114
|
}
|
|
18080
18115
|
if (ok) continue;
|
|
18081
|
-
const stillLive = await
|
|
18116
|
+
const stillLive = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(staleId) : ctx.persistence.get(staleId)).catch(() => null);
|
|
18082
18117
|
if (stillLive && !stillLive.supersededBy) liveLeftovers.push(staleId);
|
|
18083
18118
|
}
|
|
18084
18119
|
if (liveLeftovers.length > 0) {
|
|
@@ -18105,7 +18140,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
18105
18140
|
`supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
|
|
18106
18141
|
);
|
|
18107
18142
|
}
|
|
18108
|
-
const created = await
|
|
18143
|
+
const created = await ctx.persistence.create(createOpts);
|
|
18109
18144
|
cacheRowVector(
|
|
18110
18145
|
ctx.vaultCache,
|
|
18111
18146
|
created.uniqueId,
|
|
@@ -18124,11 +18159,7 @@ function unionStrings(a, b) {
|
|
|
18124
18159
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
18125
18160
|
}
|
|
18126
18161
|
async function findTombstoneMatch(embedding, embeddingModel, scope, ctx, opts) {
|
|
18127
|
-
const rows = await
|
|
18128
|
-
includeDeleted: true,
|
|
18129
|
-
scopes: [scope],
|
|
18130
|
-
...opts.folderId !== void 0 && { folderId: opts.folderId }
|
|
18131
|
-
});
|
|
18162
|
+
const rows = await ctx.persistence.tombstones(embedding, embeddingModel, scope, opts.folderId);
|
|
18132
18163
|
let bestId = null;
|
|
18133
18164
|
let bestSim = opts.threshold;
|
|
18134
18165
|
for (const row of rows) {
|
|
@@ -18195,7 +18226,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18195
18226
|
if (requestedIds.length === 0) return null;
|
|
18196
18227
|
const valid = [];
|
|
18197
18228
|
for (const id of requestedIds) {
|
|
18198
|
-
const existing = await
|
|
18229
|
+
const existing = await ctx.persistence.get(id);
|
|
18199
18230
|
if (existing && !existing.supersededBy) valid.push(id);
|
|
18200
18231
|
}
|
|
18201
18232
|
if (valid.length === 0) {
|
|
@@ -18207,7 +18238,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18207
18238
|
return { supersede: valid, content: decision.content };
|
|
18208
18239
|
}
|
|
18209
18240
|
if (decision.action === "noop" && decision.targetId) {
|
|
18210
|
-
const existing = await
|
|
18241
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
18211
18242
|
if (!existing || existing.supersededBy) {
|
|
18212
18243
|
return abandonToRace(
|
|
18213
18244
|
options,
|
|
@@ -18221,7 +18252,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18221
18252
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
18222
18253
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
18223
18254
|
const resurrect = resurrectFields(existing);
|
|
18224
|
-
const updated = await
|
|
18255
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
18225
18256
|
content: existing.content,
|
|
18226
18257
|
proofCountIncrement: 1,
|
|
18227
18258
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -18249,7 +18280,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18249
18280
|
};
|
|
18250
18281
|
}
|
|
18251
18282
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
18252
|
-
const existing = await
|
|
18283
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
18253
18284
|
if (!existing || existing.supersededBy) {
|
|
18254
18285
|
return abandonToRace(
|
|
18255
18286
|
options,
|
|
@@ -18260,12 +18291,13 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18260
18291
|
existing.sourceChunkIds ?? [],
|
|
18261
18292
|
options.sourceChunkIds ?? []
|
|
18262
18293
|
);
|
|
18263
|
-
const
|
|
18294
|
+
const generatedEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
|
|
18295
|
+
const newEmbedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
18264
18296
|
const consolidatedModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18265
18297
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
18266
18298
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
18267
18299
|
const resurrect = resurrectFields(existing);
|
|
18268
|
-
const updated = await
|
|
18300
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
18269
18301
|
content: decision.content,
|
|
18270
18302
|
proofCountIncrement: 1,
|
|
18271
18303
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -18309,7 +18341,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18309
18341
|
return null;
|
|
18310
18342
|
}
|
|
18311
18343
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
18312
|
-
const stillExists = await
|
|
18344
|
+
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
18313
18345
|
if (stillExists) {
|
|
18314
18346
|
throw new Error(`retain: merge into memory ${targetId} failed to persist`);
|
|
18315
18347
|
}
|
|
@@ -18824,9 +18856,9 @@ function createAutoExtractor(options) {
|
|
|
18824
18856
|
const persistCursor = (conversationId, messages, advancedToId, contiguous) => {
|
|
18825
18857
|
if (!cursorStore || conversationId === void 0 || !contiguous) return;
|
|
18826
18858
|
try {
|
|
18827
|
-
const
|
|
18828
|
-
if (
|
|
18829
|
-
const storedIdx = messages.findIndex((m) => m.id ===
|
|
18859
|
+
const stored2 = cursorStore.get(conversationId);
|
|
18860
|
+
if (stored2 && stored2 !== advancedToId) {
|
|
18861
|
+
const storedIdx = messages.findIndex((m) => m.id === stored2);
|
|
18830
18862
|
const newIdx = messages.findIndex((m) => m.id === advancedToId);
|
|
18831
18863
|
if (storedIdx !== -1 && newIdx !== -1 && storedIdx >= newIdx) return;
|
|
18832
18864
|
}
|
|
@@ -19795,7 +19827,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
19795
19827
|
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
19796
19828
|
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
19797
19829
|
if (chunksScopeRestricted) degraded.push("chunks-scope-restricted");
|
|
19798
|
-
const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
|
|
19830
|
+
const laneRan = types.includes("fact") && (!!ctx.factSource || !!ctx.vaultCtx && !!ctx.vaultCache) || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
|
|
19799
19831
|
const scores = admitted.map((m) => m.score);
|
|
19800
19832
|
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
19801
19833
|
const diagnostics = {
|
|
@@ -19837,7 +19869,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
19837
19869
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
19838
19870
|
}
|
|
19839
19871
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
19840
|
-
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
19872
|
+
const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
|
|
19841
19873
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
19842
19874
|
const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
|
|
19843
19875
|
const prepStart = nowMs2();
|
|
@@ -19867,7 +19899,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
19867
19899
|
safeLane(
|
|
19868
19900
|
"graph",
|
|
19869
19901
|
() => graphLaneFailed = true,
|
|
19870
|
-
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
19902
|
+
() => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
19871
19903
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
19872
19904
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
19873
19905
|
...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
|
|
@@ -19878,13 +19910,13 @@ async function recall(query, ctx, options = {}) {
|
|
|
19878
19910
|
wantsTemporal ? safeLane(
|
|
19879
19911
|
"temporal",
|
|
19880
19912
|
() => temporalLaneFailed = true,
|
|
19881
|
-
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
19913
|
+
() => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
19882
19914
|
) : Promise.resolve([])
|
|
19883
19915
|
]);
|
|
19884
19916
|
prepMs = nowMs2() - prepStart;
|
|
19885
19917
|
graphLaneCount = entityRanking.length;
|
|
19886
19918
|
temporalLaneCount = temporalRanking.length;
|
|
19887
|
-
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
19919
|
+
if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
|
|
19888
19920
|
const factStart = nowMs2();
|
|
19889
19921
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
19890
19922
|
factFloor = vaultMinScore;
|
|
@@ -19900,50 +19932,50 @@ async function recall(query, ctx, options = {}) {
|
|
|
19900
19932
|
rankedOnCosine: factRankedOnCosine,
|
|
19901
19933
|
decryptLast: factDecryptLast,
|
|
19902
19934
|
rowsDecrypted: factRowsDecrypted
|
|
19903
|
-
} = await searchVaultMemoriesWithSize(
|
|
19904
|
-
|
|
19935
|
+
} = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
|
|
19936
|
+
searchQuery,
|
|
19905
19937
|
ctx.vaultCtx,
|
|
19906
19938
|
ctx.embeddingOptions,
|
|
19907
19939
|
ctx.vaultCache,
|
|
19908
|
-
|
|
19909
|
-
|
|
19910
|
-
|
|
19911
|
-
|
|
19912
|
-
|
|
19913
|
-
|
|
19914
|
-
|
|
19915
|
-
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
|
|
19920
|
-
|
|
19921
|
-
|
|
19922
|
-
|
|
19923
|
-
|
|
19924
|
-
|
|
19925
|
-
|
|
19926
|
-
|
|
19927
|
-
|
|
19928
|
-
|
|
19929
|
-
|
|
19930
|
-
|
|
19931
|
-
|
|
19932
|
-
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
19936
|
-
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
19941
|
-
|
|
19942
|
-
|
|
19943
|
-
|
|
19944
|
-
|
|
19945
|
-
|
|
19946
|
-
);
|
|
19940
|
+
searchOptions
|
|
19941
|
+
)))(query, {
|
|
19942
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
19943
|
+
minSimilarity: vaultMinScore,
|
|
19944
|
+
useFusion: true,
|
|
19945
|
+
rerank: flags.rerank,
|
|
19946
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
19947
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
19948
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
19949
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
19950
|
+
},
|
|
19951
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
19952
|
+
...options.recency && { recency: options.recency },
|
|
19953
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
19954
|
+
...options.supersessionBoost !== void 0 && {
|
|
19955
|
+
supersessionBoost: options.supersessionBoost
|
|
19956
|
+
},
|
|
19957
|
+
...options.supersessionWindow !== void 0 && {
|
|
19958
|
+
supersessionWindow: options.supersessionWindow
|
|
19959
|
+
},
|
|
19960
|
+
...options.proofCountAlpha !== void 0 && {
|
|
19961
|
+
proofCountAlpha: options.proofCountAlpha
|
|
19962
|
+
},
|
|
19963
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
19964
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
19965
|
+
},
|
|
19966
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
19967
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
19968
|
+
...subQueries && { subQueries },
|
|
19969
|
+
...options.scopes && { scopes: options.scopes },
|
|
19970
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
19971
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
19972
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
19973
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
19974
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
19975
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
19976
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
19977
|
+
queryEmbedTotalTimeoutMs
|
|
19978
|
+
});
|
|
19947
19979
|
factResults.push(
|
|
19948
19980
|
...dedupeBy(
|
|
19949
19981
|
results,
|
|
@@ -20748,26 +20780,26 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
20748
20780
|
};
|
|
20749
20781
|
const inputs = [];
|
|
20750
20782
|
for (const id of new Set(memoryIds)) {
|
|
20751
|
-
let
|
|
20783
|
+
let record2;
|
|
20752
20784
|
try {
|
|
20753
|
-
|
|
20785
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
20754
20786
|
} catch (err) {
|
|
20755
20787
|
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
20756
20788
|
skip(id, "not-found");
|
|
20757
20789
|
continue;
|
|
20758
20790
|
}
|
|
20759
|
-
if (
|
|
20791
|
+
if (record2.isDeleted || ctx.userId !== void 0 && record2.userId !== ctx.userId || record2.topicsUserManaged) {
|
|
20760
20792
|
skip(id, "excluded");
|
|
20761
20793
|
continue;
|
|
20762
20794
|
}
|
|
20763
20795
|
try {
|
|
20764
|
-
const
|
|
20765
|
-
|
|
20796
|
+
const stored2 = await vaultMemoryToStored(
|
|
20797
|
+
record2,
|
|
20766
20798
|
ctx.walletAddress,
|
|
20767
20799
|
ctx.signMessage,
|
|
20768
20800
|
ctx.embeddedWalletSigner
|
|
20769
20801
|
);
|
|
20770
|
-
inputs.push({ id, content:
|
|
20802
|
+
inputs.push({ id, content: stored2.content });
|
|
20771
20803
|
} catch (err) {
|
|
20772
20804
|
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
20773
20805
|
skip(id, "unreadable");
|
|
@@ -20952,6 +20984,773 @@ function createLocalMemoryStore(options) {
|
|
|
20952
20984
|
};
|
|
20953
20985
|
}
|
|
20954
20986
|
|
|
20987
|
+
// src/lib/memory/store/remotePersistence.ts
|
|
20988
|
+
var RemoteMemoryError = class extends Error {
|
|
20989
|
+
constructor(message, status, code) {
|
|
20990
|
+
super(message);
|
|
20991
|
+
this.status = status;
|
|
20992
|
+
this.code = code;
|
|
20993
|
+
this.name = "RemoteMemoryError";
|
|
20994
|
+
}
|
|
20995
|
+
};
|
|
20996
|
+
var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
|
|
20997
|
+
var memoryFields = {
|
|
20998
|
+
memory_id: true,
|
|
20999
|
+
content: true,
|
|
21000
|
+
scope: true,
|
|
21001
|
+
created_at: true,
|
|
21002
|
+
updated_at: true,
|
|
21003
|
+
is_deleted: true,
|
|
21004
|
+
embedding: true,
|
|
21005
|
+
embedding_model: true,
|
|
21006
|
+
kind: true,
|
|
21007
|
+
kind_value: true,
|
|
21008
|
+
level: true,
|
|
21009
|
+
folder_id: true,
|
|
21010
|
+
source_chunk_ids: true,
|
|
21011
|
+
proof_count: true,
|
|
21012
|
+
source: true,
|
|
21013
|
+
event_time_start: true,
|
|
21014
|
+
event_time_end: true,
|
|
21015
|
+
event_time_kind: true,
|
|
21016
|
+
topics_user_managed: true,
|
|
21017
|
+
topics: true,
|
|
21018
|
+
topics_updated_at: true,
|
|
21019
|
+
media: true,
|
|
21020
|
+
topics_extracted_at: true,
|
|
21021
|
+
topics_extracted_version: true,
|
|
21022
|
+
superseded_by: true,
|
|
21023
|
+
superseded_at: true,
|
|
21024
|
+
last_observed_at: true,
|
|
21025
|
+
fact_type: true,
|
|
21026
|
+
archived_at: true,
|
|
21027
|
+
trust_tier: true,
|
|
21028
|
+
visibility: true,
|
|
21029
|
+
twin_opt_in: true,
|
|
21030
|
+
published_at: true,
|
|
21031
|
+
geohash: true
|
|
21032
|
+
};
|
|
21033
|
+
var candidateListLimits = [
|
|
21034
|
+
["scopes", 20],
|
|
21035
|
+
["fact_types", 20],
|
|
21036
|
+
["memory_ids", 1e3],
|
|
21037
|
+
["force_ids", 100]
|
|
21038
|
+
];
|
|
21039
|
+
function record(value) {
|
|
21040
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21041
|
+
}
|
|
21042
|
+
function memoryRecord(value) {
|
|
21043
|
+
if (!record(value) || !record(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))) {
|
|
21044
|
+
throw new Error("Invalid nearby private-memory response");
|
|
21045
|
+
}
|
|
21046
|
+
return value;
|
|
21047
|
+
}
|
|
21048
|
+
async function createRemoteMemoryPersistence(options) {
|
|
21049
|
+
const base = new URL(options.baseUrl);
|
|
21050
|
+
if (!/^https?:$/.test(base.protocol) || base.username || base.password || base.search || base.hash) {
|
|
21051
|
+
throw new Error(
|
|
21052
|
+
"baseUrl must be an HTTP(S) origin or base path without credentials, query or fragment"
|
|
21053
|
+
);
|
|
21054
|
+
}
|
|
21055
|
+
if (!options.keyId || options.keyId.length > 256)
|
|
21056
|
+
throw new Error("A canonical keyId is required");
|
|
21057
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
21058
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
21059
|
+
throw new Error("timeoutMs must be a positive number");
|
|
21060
|
+
const root = base.href.replace(/\/$/, "") + "/api/private-memories";
|
|
21061
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
21062
|
+
const request = async (path, init = {}, signal) => {
|
|
21063
|
+
const controller = new AbortController();
|
|
21064
|
+
let timedOut = false;
|
|
21065
|
+
const timer = setTimeout(() => {
|
|
21066
|
+
timedOut = true;
|
|
21067
|
+
controller.abort();
|
|
21068
|
+
}, timeoutMs);
|
|
21069
|
+
const forwardAbort = () => controller.abort(signal?.reason);
|
|
21070
|
+
if (signal?.aborted) forwardAbort();
|
|
21071
|
+
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
21072
|
+
let rejectAborted;
|
|
21073
|
+
const aborted = new Promise((_, reject) => {
|
|
21074
|
+
rejectAborted = () => reject(
|
|
21075
|
+
controller.signal.reason instanceof Error ? controller.signal.reason : new Error("Nearby request aborted")
|
|
21076
|
+
);
|
|
21077
|
+
if (controller.signal.aborted) rejectAborted();
|
|
21078
|
+
else controller.signal.addEventListener("abort", rejectAborted, { once: true });
|
|
21079
|
+
});
|
|
21080
|
+
aborted.catch(() => void 0);
|
|
21081
|
+
try {
|
|
21082
|
+
const token = await Promise.race([options.getToken(), aborted]);
|
|
21083
|
+
if (controller.signal.aborted) await aborted;
|
|
21084
|
+
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
21085
|
+
const response = await fetcher(root + path, {
|
|
21086
|
+
...init,
|
|
21087
|
+
headers: {
|
|
21088
|
+
Authorization: `Bearer ${token}`,
|
|
21089
|
+
...init.body ? { "Content-Type": "application/json" } : {}
|
|
21090
|
+
},
|
|
21091
|
+
redirect: "error",
|
|
21092
|
+
signal: controller.signal
|
|
21093
|
+
});
|
|
21094
|
+
if (!response.ok) {
|
|
21095
|
+
const body = await response.json().catch(() => null);
|
|
21096
|
+
throw new RemoteMemoryError(
|
|
21097
|
+
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
21098
|
+
response.status,
|
|
21099
|
+
record(body) && typeof body.code === "string" ? body.code : void 0
|
|
21100
|
+
);
|
|
21101
|
+
}
|
|
21102
|
+
return await response.json();
|
|
21103
|
+
} catch (error) {
|
|
21104
|
+
if (timedOut) throw new RemoteMemoryError("Nearby request timed out", 408, "timeout");
|
|
21105
|
+
throw error;
|
|
21106
|
+
} finally {
|
|
21107
|
+
clearTimeout(timer);
|
|
21108
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
21109
|
+
if (rejectAborted) controller.signal.removeEventListener("abort", rejectAborted);
|
|
21110
|
+
}
|
|
21111
|
+
};
|
|
21112
|
+
const account = await request("/account", {}, options.signal);
|
|
21113
|
+
if (!record(account) || account.state !== "active") {
|
|
21114
|
+
throw new RemoteMemoryError(
|
|
21115
|
+
"Complete and verify migration before using remote memories",
|
|
21116
|
+
409,
|
|
21117
|
+
"memory_not_active"
|
|
21118
|
+
);
|
|
21119
|
+
}
|
|
21120
|
+
if (account.key_id !== options.keyId) {
|
|
21121
|
+
throw new RemoteMemoryError(
|
|
21122
|
+
"The canonical memory key does not match this account",
|
|
21123
|
+
409,
|
|
21124
|
+
"key_mismatch"
|
|
21125
|
+
);
|
|
21126
|
+
}
|
|
21127
|
+
const snapshots = /* @__PURE__ */ new WeakMap();
|
|
21128
|
+
const decode = async (value) => {
|
|
21129
|
+
const item = memoryRecord(value);
|
|
21130
|
+
const decrypt = async (ciphertext) => {
|
|
21131
|
+
if (!ciphertextPattern.test(ciphertext))
|
|
21132
|
+
throw new Error("Nearby returned unencrypted memory content");
|
|
21133
|
+
const plaintext = await options.decrypt(ciphertext);
|
|
21134
|
+
if (plaintext === ciphertext) throw new Error("Memory decryption failed");
|
|
21135
|
+
return plaintext;
|
|
21136
|
+
};
|
|
21137
|
+
const decoded = {
|
|
21138
|
+
...item,
|
|
21139
|
+
memory: {
|
|
21140
|
+
...item.memory,
|
|
21141
|
+
content: await decrypt(item.memory.content),
|
|
21142
|
+
...item.memory.kind_value !== void 0 && {
|
|
21143
|
+
kind_value: await decrypt(item.memory.kind_value)
|
|
21144
|
+
}
|
|
21145
|
+
}
|
|
21146
|
+
};
|
|
21147
|
+
return remember(decoded, item);
|
|
21148
|
+
};
|
|
21149
|
+
const remember = (decoded, item) => {
|
|
21150
|
+
snapshots.set(decoded, {
|
|
21151
|
+
id: item.memory.memory_id,
|
|
21152
|
+
version: item.version,
|
|
21153
|
+
content: decoded.memory.content,
|
|
21154
|
+
kindValue: decoded.memory.kind_value,
|
|
21155
|
+
encryptedContent: item.memory.content,
|
|
21156
|
+
encryptedKindValue: item.memory.kind_value
|
|
21157
|
+
});
|
|
21158
|
+
return decoded;
|
|
21159
|
+
};
|
|
21160
|
+
const decodeAll = async (values) => {
|
|
21161
|
+
const records = values.map(memoryRecord);
|
|
21162
|
+
const settled = await Promise.allSettled(records.map(decode));
|
|
21163
|
+
const items = [];
|
|
21164
|
+
const failed = [];
|
|
21165
|
+
settled.forEach((result, i) => {
|
|
21166
|
+
if (result.status === "fulfilled") items.push(result.value);
|
|
21167
|
+
else
|
|
21168
|
+
failed.push({
|
|
21169
|
+
memory_id: records[i].memory.memory_id,
|
|
21170
|
+
version: records[i].version,
|
|
21171
|
+
error: result.reason instanceof Error ? result.reason : new Error(String(result.reason))
|
|
21172
|
+
});
|
|
21173
|
+
});
|
|
21174
|
+
return { items, failed };
|
|
21175
|
+
};
|
|
21176
|
+
const decodeCommitted = async (value, write) => {
|
|
21177
|
+
const item = memoryRecord(value);
|
|
21178
|
+
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)
|
|
21179
|
+
return decode(item);
|
|
21180
|
+
return remember(
|
|
21181
|
+
{
|
|
21182
|
+
...item,
|
|
21183
|
+
memory: {
|
|
21184
|
+
...item.memory,
|
|
21185
|
+
content: write.content,
|
|
21186
|
+
...write.kindValue !== void 0 && { kind_value: write.kindValue }
|
|
21187
|
+
}
|
|
21188
|
+
},
|
|
21189
|
+
item
|
|
21190
|
+
);
|
|
21191
|
+
};
|
|
21192
|
+
const encryptField2 = async (plaintext) => {
|
|
21193
|
+
const ciphertext = await options.encrypt(plaintext);
|
|
21194
|
+
if (ciphertext === plaintext || !ciphertextPattern.test(ciphertext))
|
|
21195
|
+
throw new Error("Field encryption must return SDK ciphertext; refusing to upload plaintext");
|
|
21196
|
+
return ciphertext;
|
|
21197
|
+
};
|
|
21198
|
+
const memoryPath = (id) => {
|
|
21199
|
+
if (!id || id.length > 128) throw new Error("memory_id must be 1\u2013128 characters");
|
|
21200
|
+
return "/memories/" + encodeURIComponent(id);
|
|
21201
|
+
};
|
|
21202
|
+
const prepareWrite = async (memory, expectedVersion, signal) => {
|
|
21203
|
+
const unknown = Object.keys(memory).filter(
|
|
21204
|
+
(key) => !Object.prototype.hasOwnProperty.call(memoryFields, key)
|
|
21205
|
+
);
|
|
21206
|
+
if (unknown.length) {
|
|
21207
|
+
throw new RemoteMemoryError(
|
|
21208
|
+
`Unknown private-memory fields (${unknown.join(", ")}); refusing to forward them`,
|
|
21209
|
+
400,
|
|
21210
|
+
"unknown_field"
|
|
21211
|
+
);
|
|
21212
|
+
}
|
|
21213
|
+
memory = { ...memory, ...memory.embedding && { embedding: [...memory.embedding] } };
|
|
21214
|
+
const path = memoryPath(memory.memory_id);
|
|
21215
|
+
const snapshot = typeof expectedVersion === "number" ? void 0 : snapshots.get(expectedVersion);
|
|
21216
|
+
if (typeof expectedVersion !== "number" && (!snapshot || snapshot.id !== memory.memory_id || snapshot.version !== expectedVersion.version))
|
|
21217
|
+
throw new Error(
|
|
21218
|
+
"Expected snapshot must be an unmodified version from this persistence instance"
|
|
21219
|
+
);
|
|
21220
|
+
expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
|
|
21221
|
+
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
21222
|
+
throw new Error("expectedVersion must be a nonnegative integer");
|
|
21223
|
+
const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
|
|
21224
|
+
let existing;
|
|
21225
|
+
if (expectedVersion !== 0 && !snapshot) {
|
|
21226
|
+
try {
|
|
21227
|
+
existing = memoryRecord(await request(path, {}, signal));
|
|
21228
|
+
} catch (error) {
|
|
21229
|
+
if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
|
|
21230
|
+
throw error;
|
|
21231
|
+
}
|
|
21232
|
+
}
|
|
21233
|
+
if (existing && existing.version !== expectedVersion) throw conflict();
|
|
21234
|
+
const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
|
|
21235
|
+
const content = (snapshot?.content ?? decoded?.memory.content) === memory.content ? snapshot?.encryptedContent ?? existing.memory.content : await encryptField2(memory.content);
|
|
21236
|
+
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);
|
|
21237
|
+
return {
|
|
21238
|
+
body: {
|
|
21239
|
+
expected_version: expectedVersion,
|
|
21240
|
+
memory: { ...memory, content, ...kindValue !== void 0 && { kind_value: kindValue } }
|
|
21241
|
+
},
|
|
21242
|
+
content: memory.content,
|
|
21243
|
+
kindValue: memory.kind_value
|
|
21244
|
+
};
|
|
21245
|
+
};
|
|
21246
|
+
const fetchCandidates = async (embedding, candidateOptions, withCounts) => {
|
|
21247
|
+
const limit = candidateOptions.limit ?? 100;
|
|
21248
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
21249
|
+
throw new Error("Candidate limit must be 1\u2013100");
|
|
21250
|
+
for (const [key, max] of candidateListLimits) {
|
|
21251
|
+
const values = candidateOptions[key];
|
|
21252
|
+
if (values && values.length > max)
|
|
21253
|
+
throw new Error(`Candidate ${key} accepts at most ${max} entries (got ${values.length})`);
|
|
21254
|
+
}
|
|
21255
|
+
const result = await request(
|
|
21256
|
+
"/candidates",
|
|
21257
|
+
{
|
|
21258
|
+
method: "POST",
|
|
21259
|
+
body: JSON.stringify({
|
|
21260
|
+
embedding,
|
|
21261
|
+
limit,
|
|
21262
|
+
force_ids: candidateOptions.force_ids ?? [],
|
|
21263
|
+
...withCounts && { with_counts: true },
|
|
21264
|
+
...Object.fromEntries(
|
|
21265
|
+
[
|
|
21266
|
+
"scopes",
|
|
21267
|
+
"memory_ids",
|
|
21268
|
+
"embedding_model",
|
|
21269
|
+
"strict_model",
|
|
21270
|
+
"include_deleted",
|
|
21271
|
+
"deleted_only"
|
|
21272
|
+
].filter(
|
|
21273
|
+
(key) => candidateOptions[key] !== void 0
|
|
21274
|
+
).map((key) => [key, candidateOptions[key]])
|
|
21275
|
+
),
|
|
21276
|
+
...candidateOptions.fact_types !== void 0 && {
|
|
21277
|
+
fact_types: candidateOptions.fact_types
|
|
21278
|
+
},
|
|
21279
|
+
...candidateOptions.include_archived !== void 0 && {
|
|
21280
|
+
include_archived: candidateOptions.include_archived
|
|
21281
|
+
},
|
|
21282
|
+
...candidateOptions.include_quarantined !== void 0 && {
|
|
21283
|
+
include_quarantined: candidateOptions.include_quarantined
|
|
21284
|
+
},
|
|
21285
|
+
...candidateOptions.include_superseded !== void 0 && {
|
|
21286
|
+
include_superseded: candidateOptions.include_superseded
|
|
21287
|
+
}
|
|
21288
|
+
})
|
|
21289
|
+
},
|
|
21290
|
+
candidateOptions.signal
|
|
21291
|
+
);
|
|
21292
|
+
if (!record(result) || !Array.isArray(result.items))
|
|
21293
|
+
throw new Error("Invalid nearby candidate response");
|
|
21294
|
+
return result;
|
|
21295
|
+
};
|
|
21296
|
+
const candidateSet = async (embedding, candidateOptions = {}) => {
|
|
21297
|
+
const result = await fetchCandidates(embedding, candidateOptions, true);
|
|
21298
|
+
if (!Number.isSafeInteger(result.total_count) || result.total_count < 0 || !Number.isSafeInteger(result.unavailable_count) || result.unavailable_count < 0)
|
|
21299
|
+
throw new Error("Invalid nearby candidate response");
|
|
21300
|
+
return {
|
|
21301
|
+
...await decodeAll(result.items),
|
|
21302
|
+
total_count: result.total_count,
|
|
21303
|
+
unavailable_count: result.unavailable_count
|
|
21304
|
+
};
|
|
21305
|
+
};
|
|
21306
|
+
return {
|
|
21307
|
+
get: async (id, signal) => {
|
|
21308
|
+
try {
|
|
21309
|
+
return await decode(await request(memoryPath(id), {}, signal));
|
|
21310
|
+
} catch (error) {
|
|
21311
|
+
if (error instanceof RemoteMemoryError && error.status === 404) return null;
|
|
21312
|
+
throw error;
|
|
21313
|
+
}
|
|
21314
|
+
},
|
|
21315
|
+
list: async (listOptions = {}) => {
|
|
21316
|
+
const { signal, ...query } = listOptions;
|
|
21317
|
+
if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200)) {
|
|
21318
|
+
throw new Error("Page limit must be 1\u2013200");
|
|
21319
|
+
}
|
|
21320
|
+
const params = new URLSearchParams();
|
|
21321
|
+
for (const key of [
|
|
21322
|
+
"cursor",
|
|
21323
|
+
"limit",
|
|
21324
|
+
"include_deleted",
|
|
21325
|
+
"include_archived",
|
|
21326
|
+
"include_quarantined",
|
|
21327
|
+
"include_superseded",
|
|
21328
|
+
"include_embeddings"
|
|
21329
|
+
]) {
|
|
21330
|
+
if (query[key] !== void 0) params.set(key, String(query[key]));
|
|
21331
|
+
}
|
|
21332
|
+
const page = await request("/memories?" + params.toString(), {}, signal);
|
|
21333
|
+
if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
|
|
21334
|
+
throw new Error("Invalid nearby private-memory page");
|
|
21335
|
+
}
|
|
21336
|
+
return {
|
|
21337
|
+
...await decodeAll(page.items),
|
|
21338
|
+
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
|
|
21339
|
+
};
|
|
21340
|
+
},
|
|
21341
|
+
put: async (memory, expectedVersion, signal) => {
|
|
21342
|
+
const write = await prepareWrite(memory, expectedVersion, signal);
|
|
21343
|
+
return decodeCommitted(
|
|
21344
|
+
await request(
|
|
21345
|
+
memoryPath(write.body.memory.memory_id),
|
|
21346
|
+
{
|
|
21347
|
+
method: "PUT",
|
|
21348
|
+
body: JSON.stringify({ key_id: options.keyId, ...write.body })
|
|
21349
|
+
},
|
|
21350
|
+
signal
|
|
21351
|
+
),
|
|
21352
|
+
write
|
|
21353
|
+
);
|
|
21354
|
+
},
|
|
21355
|
+
putMany: async (writes, signal) => {
|
|
21356
|
+
if (writes.length < 1 || writes.length > 50 || new Set(writes.map((w) => w.memory.memory_id)).size !== writes.length)
|
|
21357
|
+
throw new Error("Batch must contain 1\u201350 distinct memory ids");
|
|
21358
|
+
const prepared = await Promise.all(
|
|
21359
|
+
writes.map((w) => prepareWrite(w.memory, w.expectedVersion, signal))
|
|
21360
|
+
);
|
|
21361
|
+
const result = await request(
|
|
21362
|
+
"/memories/batch",
|
|
21363
|
+
{
|
|
21364
|
+
method: "POST",
|
|
21365
|
+
body: JSON.stringify({ key_id: options.keyId, writes: prepared.map((w) => w.body) })
|
|
21366
|
+
},
|
|
21367
|
+
signal
|
|
21368
|
+
);
|
|
21369
|
+
if (!record(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
|
|
21370
|
+
throw new Error("Invalid nearby batch response");
|
|
21371
|
+
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
21372
|
+
},
|
|
21373
|
+
candidateSet,
|
|
21374
|
+
candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
|
|
21375
|
+
};
|
|
21376
|
+
}
|
|
21377
|
+
|
|
21378
|
+
// src/lib/memory/store/remotePipeline.ts
|
|
21379
|
+
import { v7 as uuidv75 } from "uuid";
|
|
21380
|
+
function storedVector(vector) {
|
|
21381
|
+
if (!Array.isArray(vector) || vector.length !== 1536 && vector.length !== 4096 || vector.some((v) => !Number.isFinite(v)))
|
|
21382
|
+
throw new Error("Remote memories require a finite 1536/4096-dimensional vector");
|
|
21383
|
+
const out = vector.slice(0, 1536);
|
|
21384
|
+
const norm = Math.sqrt(out.reduce((sum, v) => sum + v * v, 0));
|
|
21385
|
+
if (!norm) throw new Error("Remote query/content vector has no direction after MRL truncation");
|
|
21386
|
+
return out.map((v) => v / norm);
|
|
21387
|
+
}
|
|
21388
|
+
function sourceIds(value) {
|
|
21389
|
+
if (!value) return [];
|
|
21390
|
+
try {
|
|
21391
|
+
const parsed = JSON.parse(value);
|
|
21392
|
+
return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string") : [];
|
|
21393
|
+
} catch {
|
|
21394
|
+
return [];
|
|
21395
|
+
}
|
|
21396
|
+
}
|
|
21397
|
+
function stored(row) {
|
|
21398
|
+
return {
|
|
21399
|
+
uniqueId: row.memory_id,
|
|
21400
|
+
content: row.content,
|
|
21401
|
+
scope: row.scope,
|
|
21402
|
+
folderId: row.folder_id ?? null,
|
|
21403
|
+
userId: null,
|
|
21404
|
+
embedding: row.embedding ? JSON.stringify(row.embedding) : null,
|
|
21405
|
+
embeddingModel: row.embedding_model ?? null,
|
|
21406
|
+
sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
|
|
21407
|
+
proofCount: row.proof_count ?? null,
|
|
21408
|
+
source: row.source ?? null,
|
|
21409
|
+
media: parseMedia(row.media),
|
|
21410
|
+
eventTimeStart: row.event_time_start ?? null,
|
|
21411
|
+
eventTimeEnd: row.event_time_end ?? null,
|
|
21412
|
+
eventTimeKind: row.event_time_kind ?? null,
|
|
21413
|
+
topicsUserManaged: row.topics_user_managed ?? false,
|
|
21414
|
+
topics: parseTopics(row.topics),
|
|
21415
|
+
topicsUpdatedAt: row.topics_updated_at ?? null,
|
|
21416
|
+
topicsExtractedAt: row.topics_extracted_at ?? null,
|
|
21417
|
+
topicsExtractedVersion: row.topics_extracted_version ?? null,
|
|
21418
|
+
supersededBy: row.superseded_by ?? null,
|
|
21419
|
+
supersededAt: row.superseded_at ?? null,
|
|
21420
|
+
lastObservedAt: row.last_observed_at ?? null,
|
|
21421
|
+
factType: row.fact_type ?? null,
|
|
21422
|
+
archivedAt: row.archived_at ?? null,
|
|
21423
|
+
trustTier: row.trust_tier ?? null,
|
|
21424
|
+
visibility: row.visibility === "public" ? "public" : "private",
|
|
21425
|
+
twinOptIn: row.twin_opt_in ?? false,
|
|
21426
|
+
publishedAt: row.published_at ?? null,
|
|
21427
|
+
geohash: row.geohash ?? null,
|
|
21428
|
+
createdAt: new Date(row.created_at),
|
|
21429
|
+
updatedAt: new Date(row.updated_at),
|
|
21430
|
+
isDeleted: row.is_deleted
|
|
21431
|
+
};
|
|
21432
|
+
}
|
|
21433
|
+
function createRemoteMemoryPipeline(options) {
|
|
21434
|
+
const { persistence, embeddingOptions } = options;
|
|
21435
|
+
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21436
|
+
const operation = (mode) => {
|
|
21437
|
+
const rejectUndecryptable = (failed) => {
|
|
21438
|
+
if (!failed.length) return;
|
|
21439
|
+
if (mode === "retain")
|
|
21440
|
+
throw new Error(
|
|
21441
|
+
`Remote memories could not decrypt ${failed.length} candidate row(s); refusing to retain until they are repaired`
|
|
21442
|
+
);
|
|
21443
|
+
getLogger().warn(
|
|
21444
|
+
`[memory/remote] Skipping ${failed.length} undecryptable candidate row(s)`,
|
|
21445
|
+
failed.map((failure) => failure.memory_id)
|
|
21446
|
+
);
|
|
21447
|
+
};
|
|
21448
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
21449
|
+
const remember = (items) => {
|
|
21450
|
+
items.forEach((item) => snapshots.set(item.memory.memory_id, item));
|
|
21451
|
+
return items.map((item) => stored(item.memory));
|
|
21452
|
+
};
|
|
21453
|
+
const get = async (id) => {
|
|
21454
|
+
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
21455
|
+
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
21456
|
+
snapshots.set(id, snapshot);
|
|
21457
|
+
return stored(snapshot.memory);
|
|
21458
|
+
};
|
|
21459
|
+
const prepare = async (query, search = {}) => {
|
|
21460
|
+
if (search.folderId !== void 0)
|
|
21461
|
+
throw new Error("Remote memories do not support folder filters");
|
|
21462
|
+
const facets = normalizeSubQueries(search.subQueries);
|
|
21463
|
+
const facetQueries = facets.length >= 2 ? facets : [];
|
|
21464
|
+
const start = Date.now();
|
|
21465
|
+
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
21466
|
+
const embed = (texts) => generateEmbeddings(texts, {
|
|
21467
|
+
...embeddingOptions,
|
|
21468
|
+
totalTimeoutMs: budgetMs
|
|
21469
|
+
});
|
|
21470
|
+
const embedFacets = async () => {
|
|
21471
|
+
if (!facetQueries.length) return [];
|
|
21472
|
+
try {
|
|
21473
|
+
const vectors2 = await embed(facetQueries);
|
|
21474
|
+
if (vectors2.length !== facetQueries.length)
|
|
21475
|
+
throw new Error("Incomplete facet embeddings");
|
|
21476
|
+
return vectors2.map(storedVector);
|
|
21477
|
+
} catch (error) {
|
|
21478
|
+
getLogger().warn(
|
|
21479
|
+
"[memory/remote] Facet embeddings unavailable; using primary query",
|
|
21480
|
+
error
|
|
21481
|
+
);
|
|
21482
|
+
return [];
|
|
21483
|
+
}
|
|
21484
|
+
};
|
|
21485
|
+
const [primary, facetEmbeddings] = await Promise.all([
|
|
21486
|
+
search.queryEmbedding ?? embed([query]).then((vectors2) => vectors2[0]),
|
|
21487
|
+
embedFacets()
|
|
21488
|
+
]);
|
|
21489
|
+
const queryEmbedding = storedVector(primary);
|
|
21490
|
+
const queryEmbedMs = Date.now() - start;
|
|
21491
|
+
const graph = search.entityRanking ?? [];
|
|
21492
|
+
const temporal = search.temporalRanking ?? [];
|
|
21493
|
+
const forced = /* @__PURE__ */ new Set();
|
|
21494
|
+
for (let i = 0; i < Math.max(graph.length, temporal.length) && forced.size < 100; i++) {
|
|
21495
|
+
if (graph[i] !== void 0) forced.add(graph[i]);
|
|
21496
|
+
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
21497
|
+
}
|
|
21498
|
+
const forceIds = [...forced];
|
|
21499
|
+
const windowOptions = (i, signal) => ({
|
|
21500
|
+
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
21501
|
+
force_ids: i === 0 ? forceIds : [],
|
|
21502
|
+
...search.scopes && { scopes: search.scopes },
|
|
21503
|
+
...search.factTypes && { fact_types: search.factTypes },
|
|
21504
|
+
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
21505
|
+
include_archived: search.includeArchived,
|
|
21506
|
+
embedding_model: model,
|
|
21507
|
+
...signal && { signal }
|
|
21508
|
+
});
|
|
21509
|
+
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
21510
|
+
let windows;
|
|
21511
|
+
if (mode === "retain") {
|
|
21512
|
+
windows = await Promise.all(
|
|
21513
|
+
vectors.map((embedding, i) => persistence.candidateSet(embedding, windowOptions(i)))
|
|
21514
|
+
);
|
|
21515
|
+
} else {
|
|
21516
|
+
const deadline = new AbortController();
|
|
21517
|
+
const timer = setTimeout(
|
|
21518
|
+
() => deadline.abort(
|
|
21519
|
+
new RemoteMemoryError("Remote recall exceeded its query budget", 408, "timeout")
|
|
21520
|
+
),
|
|
21521
|
+
Math.max(0, start + budgetMs - Date.now())
|
|
21522
|
+
);
|
|
21523
|
+
try {
|
|
21524
|
+
windows = await Promise.all(
|
|
21525
|
+
vectors.map(
|
|
21526
|
+
(embedding, i) => persistence.candidates(embedding, windowOptions(i, deadline.signal))
|
|
21527
|
+
)
|
|
21528
|
+
);
|
|
21529
|
+
} finally {
|
|
21530
|
+
clearTimeout(timer);
|
|
21531
|
+
}
|
|
21532
|
+
}
|
|
21533
|
+
rejectUndecryptable([
|
|
21534
|
+
...new Map(
|
|
21535
|
+
windows.flatMap((window2) => window2.failed).map((failure) => [failure.memory_id, failure])
|
|
21536
|
+
).values()
|
|
21537
|
+
]);
|
|
21538
|
+
const items = [
|
|
21539
|
+
...new Map(
|
|
21540
|
+
windows.flatMap((window2) => window2.items).map((item) => [item.memory.memory_id, item])
|
|
21541
|
+
).values()
|
|
21542
|
+
];
|
|
21543
|
+
const memories = remember(items);
|
|
21544
|
+
return {
|
|
21545
|
+
memories,
|
|
21546
|
+
embeddedItems: memories.map((memory) => ({
|
|
21547
|
+
id: memory.uniqueId,
|
|
21548
|
+
content: memory.content,
|
|
21549
|
+
embedding: JSON.parse(memory.embedding ?? "[]"),
|
|
21550
|
+
createdAt: memory.createdAt,
|
|
21551
|
+
updatedAt: memory.updatedAt,
|
|
21552
|
+
proofCount: memory.proofCount,
|
|
21553
|
+
lastObservedAt: memory.lastObservedAt,
|
|
21554
|
+
eventTimeStart: memory.eventTimeStart,
|
|
21555
|
+
eventTimeEnd: memory.eventTimeEnd,
|
|
21556
|
+
eventTimeKind: memory.eventTimeKind === "point" || memory.eventTimeKind === "range" || memory.eventTimeKind === "ongoing" ? memory.eventTimeKind : null,
|
|
21557
|
+
factType: memory.factType,
|
|
21558
|
+
sourceChunkIds: memory.sourceChunkIds
|
|
21559
|
+
})),
|
|
21560
|
+
queryEmbedding,
|
|
21561
|
+
facetEmbeddings,
|
|
21562
|
+
vaultSize: Math.max(windows[0].total_count ?? 0, items.length),
|
|
21563
|
+
embeddingFailure: windows.some((window2) => (window2.unavailable_count ?? 0) > 0),
|
|
21564
|
+
embeddingsUnavailable: (windows[0].total_count ?? items.length) > 0 && !memories.some((memory) => memory.embedding),
|
|
21565
|
+
decryptLast: true,
|
|
21566
|
+
rowsDecrypted: items.length,
|
|
21567
|
+
queryEmbedMs,
|
|
21568
|
+
rowsEmbedded: 0
|
|
21569
|
+
};
|
|
21570
|
+
};
|
|
21571
|
+
const createRow = (input) => {
|
|
21572
|
+
if (input.folderId !== void 0 && input.folderId !== null)
|
|
21573
|
+
throw new Error("Remote memories do not support folders");
|
|
21574
|
+
const now = Date.now();
|
|
21575
|
+
return {
|
|
21576
|
+
memory_id: uuidv75(),
|
|
21577
|
+
content: input.content,
|
|
21578
|
+
scope: input.scope ?? "private",
|
|
21579
|
+
created_at: now,
|
|
21580
|
+
updated_at: now,
|
|
21581
|
+
is_deleted: false,
|
|
21582
|
+
...input.embedding !== void 0 && {
|
|
21583
|
+
embedding: storedVector(JSON.parse(input.embedding)),
|
|
21584
|
+
embedding_model: input.embeddingModel
|
|
21585
|
+
},
|
|
21586
|
+
source_chunk_ids: JSON.stringify(input.sourceChunkIds ?? []),
|
|
21587
|
+
proof_count: input.proofCount ?? 1,
|
|
21588
|
+
source: input.source ?? "manual",
|
|
21589
|
+
...input.eventTime && {
|
|
21590
|
+
event_time_start: input.eventTime.start ?? void 0,
|
|
21591
|
+
event_time_end: input.eventTime.end ?? void 0,
|
|
21592
|
+
event_time_kind: input.eventTime.kind ?? void 0
|
|
21593
|
+
},
|
|
21594
|
+
fact_type: input.factType,
|
|
21595
|
+
trust_tier: normalizeTrustTier(input.trustTier) ?? void 0,
|
|
21596
|
+
geohash: input.geohash,
|
|
21597
|
+
visibility: "private",
|
|
21598
|
+
twin_opt_in: false
|
|
21599
|
+
};
|
|
21600
|
+
};
|
|
21601
|
+
const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
|
|
21602
|
+
const port = {
|
|
21603
|
+
prepare,
|
|
21604
|
+
get,
|
|
21605
|
+
getFresh: async (id) => {
|
|
21606
|
+
const current = await persistence.get(id);
|
|
21607
|
+
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
21608
|
+
},
|
|
21609
|
+
tombstones: async (embedding, embeddingModel, scope, folderId) => {
|
|
21610
|
+
if (folderId !== void 0) throw new Error("Remote memories do not support folders");
|
|
21611
|
+
const window2 = await persistence.candidateSet(storedVector(embedding), {
|
|
21612
|
+
limit: 1,
|
|
21613
|
+
scopes: [scope],
|
|
21614
|
+
embedding_model: embeddingModel,
|
|
21615
|
+
strict_model: true,
|
|
21616
|
+
include_deleted: true,
|
|
21617
|
+
deleted_only: true
|
|
21618
|
+
});
|
|
21619
|
+
rejectUndecryptable(window2.failed);
|
|
21620
|
+
return remember(window2.items);
|
|
21621
|
+
},
|
|
21622
|
+
create: (input) => write(createRow(input), 0),
|
|
21623
|
+
update: async (id, patch) => {
|
|
21624
|
+
const existing = await get(id);
|
|
21625
|
+
if (!existing) return null;
|
|
21626
|
+
const snapshot = snapshots.get(id);
|
|
21627
|
+
const memory = {
|
|
21628
|
+
...snapshot.memory,
|
|
21629
|
+
content: patch.content,
|
|
21630
|
+
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
|
|
21631
|
+
};
|
|
21632
|
+
if (patch.scope !== void 0) memory.scope = patch.scope;
|
|
21633
|
+
if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
|
|
21634
|
+
delete memory.embedding;
|
|
21635
|
+
delete memory.embedding_model;
|
|
21636
|
+
}
|
|
21637
|
+
if (patch.embedding !== void 0) {
|
|
21638
|
+
memory.embedding = patch.embedding === null ? [] : storedVector(JSON.parse(patch.embedding));
|
|
21639
|
+
memory.embedding_model = patch.embeddingModel ?? void 0;
|
|
21640
|
+
}
|
|
21641
|
+
const observed = sourceIds(memory.source_chunk_ids);
|
|
21642
|
+
const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
|
|
21643
|
+
if (patch.sourceChunkIds !== void 0)
|
|
21644
|
+
memory.source_chunk_ids = JSON.stringify(
|
|
21645
|
+
patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
|
|
21646
|
+
);
|
|
21647
|
+
if (!replay) {
|
|
21648
|
+
if (patch.proofCountIncrement !== void 0)
|
|
21649
|
+
memory.proof_count = (memory.proof_count ?? 1) + patch.proofCountIncrement;
|
|
21650
|
+
else if (patch.proofCount !== void 0) memory.proof_count = patch.proofCount;
|
|
21651
|
+
if (patch.lastObservedAt !== void 0) memory.last_observed_at = patch.lastObservedAt;
|
|
21652
|
+
}
|
|
21653
|
+
if (patch.source !== void 0) memory.source = patch.source;
|
|
21654
|
+
if (patch.factType !== void 0) memory.fact_type = patch.factType;
|
|
21655
|
+
if (patch.trustTier !== void 0)
|
|
21656
|
+
memory.trust_tier = normalizeTrustTier(patch.trustTier) ?? void 0;
|
|
21657
|
+
if (patch.topicsUserManaged !== void 0)
|
|
21658
|
+
memory.topics_user_managed = patch.topicsUserManaged;
|
|
21659
|
+
if (patch.eventTime !== void 0) {
|
|
21660
|
+
memory.event_time_start = patch.eventTime.start ?? void 0;
|
|
21661
|
+
memory.event_time_end = patch.eventTime.end ?? void 0;
|
|
21662
|
+
memory.event_time_kind = patch.eventTime.kind ?? void 0;
|
|
21663
|
+
}
|
|
21664
|
+
if (patch.restore) memory.archived_at = void 0;
|
|
21665
|
+
return write(memory, snapshot);
|
|
21666
|
+
},
|
|
21667
|
+
supersede: async (id, successor) => {
|
|
21668
|
+
const [target, newer] = await Promise.all([get(id), get(successor)]);
|
|
21669
|
+
if (!target || !newer || id === successor) return false;
|
|
21670
|
+
const old = snapshots.get(id);
|
|
21671
|
+
const next = snapshots.get(successor);
|
|
21672
|
+
remember(
|
|
21673
|
+
await persistence.putMany([
|
|
21674
|
+
{
|
|
21675
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
21676
|
+
expectedVersion: old
|
|
21677
|
+
},
|
|
21678
|
+
{ memory: next.memory, expectedVersion: next }
|
|
21679
|
+
])
|
|
21680
|
+
);
|
|
21681
|
+
return true;
|
|
21682
|
+
},
|
|
21683
|
+
createSuperseding: async (input, targetId) => {
|
|
21684
|
+
const target = await get(targetId);
|
|
21685
|
+
if (!target) return { created: null, retired: false };
|
|
21686
|
+
const snapshot = snapshots.get(targetId);
|
|
21687
|
+
const successor = createRow(input);
|
|
21688
|
+
const rows = remember(
|
|
21689
|
+
await persistence.putMany([
|
|
21690
|
+
{ memory: successor, expectedVersion: 0 },
|
|
21691
|
+
{
|
|
21692
|
+
memory: {
|
|
21693
|
+
...snapshot.memory,
|
|
21694
|
+
superseded_by: successor.memory_id,
|
|
21695
|
+
superseded_at: Date.now()
|
|
21696
|
+
},
|
|
21697
|
+
expectedVersion: snapshot
|
|
21698
|
+
}
|
|
21699
|
+
])
|
|
21700
|
+
);
|
|
21701
|
+
return { created: rows[0], retired: true };
|
|
21702
|
+
}
|
|
21703
|
+
};
|
|
21704
|
+
return { prepare, port };
|
|
21705
|
+
};
|
|
21706
|
+
return {
|
|
21707
|
+
recall: async (query, recallOptions = {}) => {
|
|
21708
|
+
const { prepare } = operation("recall");
|
|
21709
|
+
return recall(
|
|
21710
|
+
query,
|
|
21711
|
+
{
|
|
21712
|
+
embeddingOptions,
|
|
21713
|
+
factSource: {
|
|
21714
|
+
graphRanking: options.graphRanking,
|
|
21715
|
+
temporalRanking: options.temporalRanking,
|
|
21716
|
+
search: async (text12, searchOptions) => {
|
|
21717
|
+
const prepared = await prepare(text12, searchOptions);
|
|
21718
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
21719
|
+
text12,
|
|
21720
|
+
prepared,
|
|
21721
|
+
embeddingOptions,
|
|
21722
|
+
searchOptions
|
|
21723
|
+
);
|
|
21724
|
+
return {
|
|
21725
|
+
...ranked,
|
|
21726
|
+
rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
|
|
21727
|
+
decryptLast: true,
|
|
21728
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
21729
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
21730
|
+
rowsEmbedded: 0
|
|
21731
|
+
};
|
|
21732
|
+
}
|
|
21733
|
+
}
|
|
21734
|
+
},
|
|
21735
|
+
{ ...recallOptions, types: ["fact"] }
|
|
21736
|
+
);
|
|
21737
|
+
},
|
|
21738
|
+
retain: async (content, retainOptions) => {
|
|
21739
|
+
const { port } = operation("retain");
|
|
21740
|
+
return retainWithPersistence(
|
|
21741
|
+
content,
|
|
21742
|
+
{
|
|
21743
|
+
persistence: port,
|
|
21744
|
+
embeddingOptions,
|
|
21745
|
+
vaultCache: /* @__PURE__ */ new Map(),
|
|
21746
|
+
normalizeEmbedding: storedVector
|
|
21747
|
+
},
|
|
21748
|
+
retainOptions
|
|
21749
|
+
);
|
|
21750
|
+
}
|
|
21751
|
+
};
|
|
21752
|
+
}
|
|
21753
|
+
|
|
20955
21754
|
// src/lib/memory/synthesizeProfile.ts
|
|
20956
21755
|
var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
|
|
20957
21756
|
var DEFAULT_FACET_RECALL_LIMIT = 20;
|
|
@@ -27206,7 +28005,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
27206
28005
|
const recordName = `backup_${filename.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
27207
28006
|
const arrayBuffer = await content.arrayBuffer();
|
|
27208
28007
|
const base64Data = uint8ArrayToBase64(new Uint8Array(arrayBuffer));
|
|
27209
|
-
const
|
|
28008
|
+
const record2 = {
|
|
27210
28009
|
recordType: RECORD_TYPE,
|
|
27211
28010
|
recordName,
|
|
27212
28011
|
fields: {
|
|
@@ -27216,7 +28015,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
27216
28015
|
contentType: { value: content.type || "application/json" }
|
|
27217
28016
|
}
|
|
27218
28017
|
};
|
|
27219
|
-
const response = await database.saveRecords(
|
|
28018
|
+
const response = await database.saveRecords(record2);
|
|
27220
28019
|
if (!response.records || response.records.length === 0) {
|
|
27221
28020
|
throw new Error("Failed to upload file to iCloud");
|
|
27222
28021
|
}
|
|
@@ -27242,11 +28041,11 @@ async function listICloudFiles() {
|
|
|
27242
28041
|
while (response.continuationMarker) {
|
|
27243
28042
|
break;
|
|
27244
28043
|
}
|
|
27245
|
-
const files = allRecords.map((
|
|
27246
|
-
recordName:
|
|
27247
|
-
filename:
|
|
27248
|
-
modifiedAt: new Date(
|
|
27249
|
-
size: typeof
|
|
28044
|
+
const files = allRecords.map((record2) => ({
|
|
28045
|
+
recordName: record2.recordName,
|
|
28046
|
+
filename: record2.fields.filename?.value ?? "",
|
|
28047
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
28048
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
27250
28049
|
}));
|
|
27251
28050
|
return files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
27252
28051
|
}
|
|
@@ -27259,8 +28058,8 @@ async function downloadICloudFile(recordName) {
|
|
|
27259
28058
|
if (!response.records || response.records.length === 0) {
|
|
27260
28059
|
throw new Error(`File not found: ${recordName}`);
|
|
27261
28060
|
}
|
|
27262
|
-
const
|
|
27263
|
-
const dataField =
|
|
28061
|
+
const record2 = response.records[0];
|
|
28062
|
+
const dataField = record2.fields.data?.value;
|
|
27264
28063
|
if (!dataField) {
|
|
27265
28064
|
throw new Error("No data in record");
|
|
27266
28065
|
}
|
|
@@ -27294,12 +28093,12 @@ async function findICloudFile(filename) {
|
|
|
27294
28093
|
if (!response.records || response.records.length === 0) {
|
|
27295
28094
|
return null;
|
|
27296
28095
|
}
|
|
27297
|
-
const
|
|
28096
|
+
const record2 = response.records[0];
|
|
27298
28097
|
return {
|
|
27299
|
-
recordName:
|
|
27300
|
-
filename:
|
|
27301
|
-
modifiedAt: new Date(
|
|
27302
|
-
size: typeof
|
|
28098
|
+
recordName: record2.recordName,
|
|
28099
|
+
filename: record2.fields.filename?.value ?? "",
|
|
28100
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
28101
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
27303
28102
|
};
|
|
27304
28103
|
}
|
|
27305
28104
|
|
|
@@ -27457,8 +28256,8 @@ async function getStoredTokenData5(provider, walletAddress) {
|
|
|
27457
28256
|
return null;
|
|
27458
28257
|
}
|
|
27459
28258
|
}
|
|
27460
|
-
async function readTokenRow(
|
|
27461
|
-
if (
|
|
28259
|
+
async function readTokenRow(stored2, provider, walletAddress) {
|
|
28260
|
+
if (stored2.startsWith(ENCRYPTED_PREFIX6)) {
|
|
27462
28261
|
if (!walletAddress) {
|
|
27463
28262
|
getLogger().warn(
|
|
27464
28263
|
`Encrypted OAuth token found for ${provider} but no wallet address provided`
|
|
@@ -27466,7 +28265,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
27466
28265
|
return null;
|
|
27467
28266
|
}
|
|
27468
28267
|
try {
|
|
27469
|
-
const encryptedData =
|
|
28268
|
+
const encryptedData = stored2.slice(ENCRYPTED_PREFIX6.length);
|
|
27470
28269
|
let decryptedJson;
|
|
27471
28270
|
try {
|
|
27472
28271
|
decryptedJson = await decryptData(encryptedData, walletAddress);
|
|
@@ -27481,7 +28280,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
27481
28280
|
return null;
|
|
27482
28281
|
}
|
|
27483
28282
|
}
|
|
27484
|
-
return parsePlaintextToken(
|
|
28283
|
+
return parsePlaintextToken(stored2, walletAddress);
|
|
27485
28284
|
}
|
|
27486
28285
|
async function storeTokenData5(provider, data, walletAddress) {
|
|
27487
28286
|
if (typeof window === "undefined") return;
|
|
@@ -27557,8 +28356,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
27557
28356
|
const keys = [scopedKey, legacyKey];
|
|
27558
28357
|
const isEncrypted2 = (value) => !!value && value.startsWith(ENCRYPTED_PREFIX6);
|
|
27559
28358
|
const plaintextAt = (key) => {
|
|
27560
|
-
const
|
|
27561
|
-
return
|
|
28359
|
+
const stored2 = sessionStorage.getItem(key) ?? localStorage.getItem(key);
|
|
28360
|
+
return stored2 && !isEncrypted2(stored2) ? stored2 : null;
|
|
27562
28361
|
};
|
|
27563
28362
|
let tokenToMigrate = null;
|
|
27564
28363
|
for (const key of keys) {
|
|
@@ -27570,8 +28369,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
27570
28369
|
}
|
|
27571
28370
|
if (!tokenToMigrate) {
|
|
27572
28371
|
for (const key of keys) {
|
|
27573
|
-
const
|
|
27574
|
-
if (isEncrypted2(localStorage.getItem(key)) &&
|
|
28372
|
+
const stored2 = sessionStorage.getItem(key);
|
|
28373
|
+
if (isEncrypted2(localStorage.getItem(key)) && stored2 && !isEncrypted2(stored2)) {
|
|
27575
28374
|
sessionStorage.removeItem(key);
|
|
27576
28375
|
}
|
|
27577
28376
|
}
|
|
@@ -27627,17 +28426,17 @@ function storeOAuthState2(state) {
|
|
|
27627
28426
|
}
|
|
27628
28427
|
function getAndClearOAuthState4() {
|
|
27629
28428
|
if (typeof window === "undefined") return null;
|
|
27630
|
-
const
|
|
28429
|
+
const stored2 = sessionStorage.getItem(STATE_STORAGE_KEY);
|
|
27631
28430
|
sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
27632
|
-
if (!
|
|
28431
|
+
if (!stored2) return null;
|
|
27633
28432
|
try {
|
|
27634
|
-
const parsed = JSON.parse(
|
|
28433
|
+
const parsed = JSON.parse(stored2);
|
|
27635
28434
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
27636
28435
|
return parsed.state;
|
|
27637
28436
|
}
|
|
27638
28437
|
} catch {
|
|
27639
28438
|
}
|
|
27640
|
-
return
|
|
28439
|
+
return stored2;
|
|
27641
28440
|
}
|
|
27642
28441
|
function isDropboxCallback() {
|
|
27643
28442
|
if (typeof window === "undefined") return false;
|
|
@@ -27820,17 +28619,17 @@ function storeOAuthState3(state) {
|
|
|
27820
28619
|
}
|
|
27821
28620
|
function getAndClearOAuthState5() {
|
|
27822
28621
|
if (typeof window === "undefined") return null;
|
|
27823
|
-
const
|
|
28622
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY4);
|
|
27824
28623
|
sessionStorage.removeItem(CODE_STORAGE_KEY4);
|
|
27825
|
-
if (!
|
|
28624
|
+
if (!stored2) return null;
|
|
27826
28625
|
try {
|
|
27827
|
-
const parsed = JSON.parse(
|
|
28626
|
+
const parsed = JSON.parse(stored2);
|
|
27828
28627
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
27829
28628
|
return parsed.state;
|
|
27830
28629
|
}
|
|
27831
28630
|
} catch {
|
|
27832
28631
|
}
|
|
27833
|
-
return
|
|
28632
|
+
return stored2;
|
|
27834
28633
|
}
|
|
27835
28634
|
function isGoogleDriveCallback() {
|
|
27836
28635
|
if (typeof window === "undefined") return false;
|
|
@@ -29760,18 +30559,18 @@ async function blobToDataUri(blob) {
|
|
|
29760
30559
|
reader.readAsDataURL(blob);
|
|
29761
30560
|
});
|
|
29762
30561
|
}
|
|
29763
|
-
async function storedToLlmapiMessage(
|
|
29764
|
-
let textContent =
|
|
30562
|
+
async function storedToLlmapiMessage(stored2, encryptionKey, resolveMediaByIds) {
|
|
30563
|
+
let textContent = stored2.content;
|
|
29765
30564
|
const fileUrlMap = /* @__PURE__ */ new Map();
|
|
29766
30565
|
const imageParts = [];
|
|
29767
|
-
if (
|
|
29768
|
-
for (const file of
|
|
30566
|
+
if (stored2.role !== "assistant" && stored2.files?.length) {
|
|
30567
|
+
for (const file of stored2.files) {
|
|
29769
30568
|
if (isSendableImageURL(file.url)) {
|
|
29770
30569
|
imageParts.push({
|
|
29771
30570
|
type: "image_url",
|
|
29772
30571
|
image_url: { url: file.url }
|
|
29773
30572
|
});
|
|
29774
|
-
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl,
|
|
30573
|
+
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
29775
30574
|
imageParts.push({
|
|
29776
30575
|
type: "image_url",
|
|
29777
30576
|
image_url: { url: file.sourceUrl }
|
|
@@ -29791,11 +30590,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29791
30590
|
}
|
|
29792
30591
|
}
|
|
29793
30592
|
}
|
|
29794
|
-
} else if (
|
|
30593
|
+
} else if (stored2.role === "assistant" && stored2.files?.length) {
|
|
29795
30594
|
const expiredFileIds = [];
|
|
29796
|
-
for (const file of
|
|
30595
|
+
for (const file of stored2.files) {
|
|
29797
30596
|
if (file.sourceUrl) {
|
|
29798
|
-
if (!isR2UrlExpired(file.sourceUrl,
|
|
30597
|
+
if (!isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
29799
30598
|
fileUrlMap.set(file.id, file.sourceUrl);
|
|
29800
30599
|
} else {
|
|
29801
30600
|
expiredFileIds.push(file.id);
|
|
@@ -29808,11 +30607,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29808
30607
|
[${expiredFileIds.length} expired image URL${expiredFileIds.length > 1 ? "s" : ""} omitted \u2014 the user can still see ${expiredFileIds.length > 1 ? "them" : "it"} locally]`;
|
|
29809
30608
|
}
|
|
29810
30609
|
}
|
|
29811
|
-
if (
|
|
30610
|
+
if (stored2.fileIds?.length && resolveMediaByIds) {
|
|
29812
30611
|
try {
|
|
29813
|
-
const mediaItems = await resolveMediaByIds(
|
|
30612
|
+
const mediaItems = await resolveMediaByIds(stored2.fileIds);
|
|
29814
30613
|
for (const media of mediaItems) {
|
|
29815
|
-
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl,
|
|
30614
|
+
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl, stored2.createdAt)) {
|
|
29816
30615
|
fileUrlMap.set(media.mediaId, media.sourceUrl);
|
|
29817
30616
|
}
|
|
29818
30617
|
}
|
|
@@ -29836,7 +30635,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29836
30635
|
return "";
|
|
29837
30636
|
}
|
|
29838
30637
|
);
|
|
29839
|
-
if (
|
|
30638
|
+
if (stored2.role === "assistant" && fileUrlMap.size > 0) {
|
|
29840
30639
|
const unreferencedImages = [...fileUrlMap.entries()].filter(
|
|
29841
30640
|
([, url]) => !textContent.includes(url)
|
|
29842
30641
|
);
|
|
@@ -29848,11 +30647,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29848
30647
|
textContent = textContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
29849
30648
|
const content = [{ type: "text", text: textContent }, ...imageParts];
|
|
29850
30649
|
const messages = [];
|
|
29851
|
-
if (
|
|
30650
|
+
if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
|
|
29852
30651
|
messages.push({
|
|
29853
|
-
role:
|
|
30652
|
+
role: stored2.role,
|
|
29854
30653
|
content: void 0,
|
|
29855
|
-
tool_calls:
|
|
30654
|
+
tool_calls: stored2.toolCallEvents.map((event) => ({
|
|
29856
30655
|
id: event.id,
|
|
29857
30656
|
type: "function",
|
|
29858
30657
|
function: {
|
|
@@ -29861,7 +30660,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29861
30660
|
}
|
|
29862
30661
|
}))
|
|
29863
30662
|
});
|
|
29864
|
-
for (const event of
|
|
30663
|
+
for (const event of stored2.toolCallEvents) {
|
|
29865
30664
|
if (event.id && event.output !== void 0 && event.output !== null) {
|
|
29866
30665
|
messages.push({
|
|
29867
30666
|
role: "tool",
|
|
@@ -29872,12 +30671,12 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29872
30671
|
}
|
|
29873
30672
|
const postToolText = textContent.replace(/!\[[^\]]*\]\(https?:\/\/[a-z0-9]+\.r2\.cloudflarestorage\.com\/[^)]+\)/g, "").replace(/https?:\/\/[a-z0-9]+\.r2\.cloudflarestorage\.com\/[^\s)]+/g, "").replace(/!\[[^\]]*\]\(https?:\/\/[^)\s]+\/api\/v1\/media\/[^/)\s]+\/[^)]+\)/g, "").replace(/https?:\/\/[^\s)]+\/api\/v1\/media\/[^/\s)]+\/[^\s)]+/g, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
29874
30673
|
messages.push({
|
|
29875
|
-
role:
|
|
30674
|
+
role: stored2.role,
|
|
29876
30675
|
content: [{ type: "text", text: postToolText }]
|
|
29877
30676
|
});
|
|
29878
30677
|
} else {
|
|
29879
30678
|
messages.push({
|
|
29880
|
-
role:
|
|
30679
|
+
role: stored2.role,
|
|
29881
30680
|
content
|
|
29882
30681
|
});
|
|
29883
30682
|
}
|
|
@@ -33708,19 +34507,19 @@ function startObserve(entry, walletAddress) {
|
|
|
33708
34507
|
"updated_at"
|
|
33709
34508
|
]).subscribe({
|
|
33710
34509
|
next: (records) => {
|
|
33711
|
-
const
|
|
33712
|
-
if (!
|
|
34510
|
+
const record2 = records[0];
|
|
34511
|
+
if (!record2) return;
|
|
33713
34512
|
const patch = {
|
|
33714
34513
|
userPreference: {
|
|
33715
|
-
uniqueId:
|
|
33716
|
-
walletAddress:
|
|
33717
|
-
nickname:
|
|
33718
|
-
occupation:
|
|
33719
|
-
description:
|
|
33720
|
-
models:
|
|
33721
|
-
personality:
|
|
33722
|
-
createdAt:
|
|
33723
|
-
updatedAt:
|
|
34514
|
+
uniqueId: record2.id,
|
|
34515
|
+
walletAddress: record2.walletAddress,
|
|
34516
|
+
nickname: record2.nickname,
|
|
34517
|
+
occupation: record2.occupation,
|
|
34518
|
+
description: record2.description,
|
|
34519
|
+
models: record2.models,
|
|
34520
|
+
personality: record2.personality,
|
|
34521
|
+
createdAt: record2.createdAt,
|
|
34522
|
+
updatedAt: record2.updatedAt
|
|
33724
34523
|
}
|
|
33725
34524
|
};
|
|
33726
34525
|
if (isInitialEmission) {
|
|
@@ -34943,6 +35742,7 @@ export {
|
|
|
34943
35742
|
R2_DEFAULT_TTL_MS,
|
|
34944
35743
|
RECALL_MAX_LIMIT,
|
|
34945
35744
|
RECALL_TOOL_NAME,
|
|
35745
|
+
RemoteMemoryError,
|
|
34946
35746
|
RerankerUnavailableError,
|
|
34947
35747
|
SDK_SCHEMA_VERSION,
|
|
34948
35748
|
SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -35034,6 +35834,8 @@ export {
|
|
|
35034
35834
|
createPlatformCursorStore,
|
|
35035
35835
|
createProjectOp,
|
|
35036
35836
|
createRecallTool,
|
|
35837
|
+
createRemoteMemoryPersistence,
|
|
35838
|
+
createRemoteMemoryPipeline,
|
|
35037
35839
|
createSavedToolOp,
|
|
35038
35840
|
createServerToolsFilter,
|
|
35039
35841
|
createStockPricePreProcessor,
|