@anuma/sdk 6.33.2 → 6.35.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 +1304 -300
- package/dist/expo/index.d.mts +278 -11
- package/dist/expo/index.d.ts +278 -11
- package/dist/expo/index.mjs +1297 -300
- package/dist/index.cjs +18 -6
- package/dist/index.mjs +18 -6
- package/dist/memory/context.d.mts +21 -1
- package/dist/memory/context.d.ts +21 -1
- package/dist/react/index.cjs +1385 -381
- package/dist/react/index.d.mts +311 -11
- package/dist/react/index.d.ts +311 -11
- package/dist/react/index.mjs +1378 -381
- package/dist/server/index.cjs +319 -99
- package/dist/server/index.d.mts +138 -11
- package/dist/server/index.d.ts +138 -11
- package/dist/server/index.mjs +316 -99
- 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()),
|
|
@@ -11306,6 +11318,15 @@ __decorateClass([
|
|
|
11306
11318
|
__decorateClass([
|
|
11307
11319
|
text6("scope")
|
|
11308
11320
|
], VaultMemory.prototype, "scope", 2);
|
|
11321
|
+
__decorateClass([
|
|
11322
|
+
field5("kind")
|
|
11323
|
+
], VaultMemory.prototype, "kind", 2);
|
|
11324
|
+
__decorateClass([
|
|
11325
|
+
field5("kind_value")
|
|
11326
|
+
], VaultMemory.prototype, "kindValue", 2);
|
|
11327
|
+
__decorateClass([
|
|
11328
|
+
field5("level")
|
|
11329
|
+
], VaultMemory.prototype, "level", 2);
|
|
11309
11330
|
__decorateClass([
|
|
11310
11331
|
field5("folder_id")
|
|
11311
11332
|
], VaultMemory.prototype, "folderId", 2);
|
|
@@ -11531,7 +11552,7 @@ __decorateClass([
|
|
|
11531
11552
|
], VaultFolder.prototype, "context", 2);
|
|
11532
11553
|
|
|
11533
11554
|
// src/lib/db/schema.ts
|
|
11534
|
-
var SDK_SCHEMA_VERSION =
|
|
11555
|
+
var SDK_SCHEMA_VERSION = 48;
|
|
11535
11556
|
var sdkSchema = appSchema2({
|
|
11536
11557
|
version: SDK_SCHEMA_VERSION,
|
|
11537
11558
|
tables: [
|
|
@@ -11626,6 +11647,9 @@ var sdkSchema = appSchema2({
|
|
|
11626
11647
|
columns: [
|
|
11627
11648
|
{ name: "content", type: "string" },
|
|
11628
11649
|
{ name: "scope", type: "string", isIndexed: true },
|
|
11650
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
11651
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
11652
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true },
|
|
11629
11653
|
{ name: "folder_id", type: "string", isOptional: true, isIndexed: true },
|
|
11630
11654
|
{ name: "created_at", type: "number", isIndexed: true },
|
|
11631
11655
|
{ name: "updated_at", type: "number", isIndexed: true },
|
|
@@ -12302,6 +12326,22 @@ var sdkMigrations = schemaMigrations2({
|
|
|
12302
12326
|
]
|
|
12303
12327
|
})
|
|
12304
12328
|
]
|
|
12329
|
+
},
|
|
12330
|
+
{
|
|
12331
|
+
toVersion: 48,
|
|
12332
|
+
steps: [
|
|
12333
|
+
addColumns2({
|
|
12334
|
+
table: "memory_vault",
|
|
12335
|
+
columns: [
|
|
12336
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
12337
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
12338
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true }
|
|
12339
|
+
]
|
|
12340
|
+
}),
|
|
12341
|
+
unsafeExecuteSql(
|
|
12342
|
+
"UPDATE memory_vault SET level = CASE WHEN scope IN ('shared', 'public') THEN 'matching' ELSE 'private' END WHERE level IS NULL;"
|
|
12343
|
+
)
|
|
12344
|
+
]
|
|
12305
12345
|
}
|
|
12306
12346
|
]
|
|
12307
12347
|
});
|
|
@@ -13172,13 +13212,13 @@ async function relinkMisclassifiedVideosOp(ctx, walletAddress) {
|
|
|
13172
13212
|
toRelink.push({ media, ext: mime.split("/")[1] || "mp4" });
|
|
13173
13213
|
continue;
|
|
13174
13214
|
}
|
|
13175
|
-
const
|
|
13215
|
+
const stored2 = await mediaToStored(
|
|
13176
13216
|
media,
|
|
13177
13217
|
ctx.walletAddress,
|
|
13178
13218
|
ctx.signMessage,
|
|
13179
13219
|
ctx.embeddedWalletSigner
|
|
13180
13220
|
);
|
|
13181
|
-
const ext = videoExtensionOf(
|
|
13221
|
+
const ext = videoExtensionOf(stored2.sourceUrl) ?? videoExtensionOf(stored2.name);
|
|
13182
13222
|
if (ext) {
|
|
13183
13223
|
toRelink.push({ media, ext });
|
|
13184
13224
|
}
|
|
@@ -13438,13 +13478,54 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
13438
13478
|
}
|
|
13439
13479
|
}
|
|
13440
13480
|
const decryptedContent = await decryptField(memory.content, address);
|
|
13481
|
+
const decryptedKindValue = typeof memory.kindValue === "string" ? await decryptField(memory.kindValue, address) : memory.kindValue;
|
|
13441
13482
|
return {
|
|
13442
13483
|
...memory,
|
|
13443
|
-
content: decryptedContent
|
|
13484
|
+
content: decryptedContent,
|
|
13485
|
+
...decryptedKindValue !== void 0 && { kindValue: decryptedKindValue }
|
|
13444
13486
|
};
|
|
13445
13487
|
}
|
|
13446
13488
|
|
|
13447
13489
|
// src/lib/db/memoryVault/types.ts
|
|
13490
|
+
var MEMORY_KINDS = [
|
|
13491
|
+
"display_name",
|
|
13492
|
+
"birth_date",
|
|
13493
|
+
"bio",
|
|
13494
|
+
"occupation",
|
|
13495
|
+
"interest",
|
|
13496
|
+
"gender",
|
|
13497
|
+
"height_cm",
|
|
13498
|
+
"looking_for",
|
|
13499
|
+
"politics",
|
|
13500
|
+
"religion",
|
|
13501
|
+
"ethnicity",
|
|
13502
|
+
"smoking",
|
|
13503
|
+
"drinking",
|
|
13504
|
+
"exercise",
|
|
13505
|
+
"sexuality",
|
|
13506
|
+
"prompt"
|
|
13507
|
+
];
|
|
13508
|
+
var MEMORY_LEVELS = ["private", "matching", "profile"];
|
|
13509
|
+
var MemoryLevelError = class extends Error {
|
|
13510
|
+
constructor(message) {
|
|
13511
|
+
super(message);
|
|
13512
|
+
this.name = "MemoryLevelError";
|
|
13513
|
+
}
|
|
13514
|
+
};
|
|
13515
|
+
var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
|
|
13516
|
+
function levelFromScope(scope) {
|
|
13517
|
+
return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
|
|
13518
|
+
}
|
|
13519
|
+
function scopeForLevel(level) {
|
|
13520
|
+
return level === "private" ? "private" : "shared";
|
|
13521
|
+
}
|
|
13522
|
+
function resolveMemoryLevel(level, scope) {
|
|
13523
|
+
return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
|
|
13524
|
+
}
|
|
13525
|
+
function levelForScopeChange(current, nextScope) {
|
|
13526
|
+
const implied = levelFromScope(nextScope);
|
|
13527
|
+
return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
|
|
13528
|
+
}
|
|
13448
13529
|
function parseMedia(value) {
|
|
13449
13530
|
if (typeof value !== "string" || value === "") return null;
|
|
13450
13531
|
try {
|
|
@@ -13474,8 +13555,58 @@ function visibilityConditions(requested) {
|
|
|
13474
13555
|
if (excluded.length === 0) return [];
|
|
13475
13556
|
return [Q8.or(Q8.where("visibility", null), Q8.where("visibility", Q8.notIn(excluded)))];
|
|
13476
13557
|
}
|
|
13477
|
-
function
|
|
13478
|
-
return
|
|
13558
|
+
function isKinded(record2) {
|
|
13559
|
+
return record2.kind !== null && record2.kind !== void 0;
|
|
13560
|
+
}
|
|
13561
|
+
function assertValidKindLevel(kind, level) {
|
|
13562
|
+
const hasKind = kind !== null && kind !== void 0;
|
|
13563
|
+
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
13564
|
+
throw new MemoryLevelError(`Unknown memory kind: ${kind}`);
|
|
13565
|
+
}
|
|
13566
|
+
if (level !== void 0 && !MEMORY_LEVELS.includes(level)) {
|
|
13567
|
+
throw new MemoryLevelError(`Unknown memory level: ${level}`);
|
|
13568
|
+
}
|
|
13569
|
+
if (level === "profile" && !hasKind) {
|
|
13570
|
+
throw new MemoryLevelError("Only a memory with a kind can be at level 'profile'");
|
|
13571
|
+
}
|
|
13572
|
+
}
|
|
13573
|
+
function resolveCreateLevel(opts) {
|
|
13574
|
+
if (opts.level !== void 0) return { level: opts.level, scope: scopeForLevel(opts.level) };
|
|
13575
|
+
if (opts.scope !== void 0) return { level: levelFromScope(opts.scope), scope: opts.scope };
|
|
13576
|
+
return { level: "private", scope: "private" };
|
|
13577
|
+
}
|
|
13578
|
+
async function encryptKindValue(ctx, value) {
|
|
13579
|
+
if (typeof value !== "string" || !ctx.walletAddress || !ctx.signMessage) return value;
|
|
13580
|
+
return encryptVaultMemoryContent(
|
|
13581
|
+
value,
|
|
13582
|
+
ctx.walletAddress,
|
|
13583
|
+
ctx.signMessage,
|
|
13584
|
+
ctx.embeddedWalletSigner
|
|
13585
|
+
);
|
|
13586
|
+
}
|
|
13587
|
+
function levelConditions(requested) {
|
|
13588
|
+
if (!requested?.length) return [];
|
|
13589
|
+
const published = ["shared", "public"];
|
|
13590
|
+
const wantsMatching = requested.includes("matching");
|
|
13591
|
+
const wantsPrivate = requested.includes("private");
|
|
13592
|
+
const unresolved = Q8.or(Q8.where("level", null), Q8.where("level", Q8.notIn([...MEMORY_LEVELS])));
|
|
13593
|
+
const byLevel = Q8.where("level", Q8.oneOf([...requested]));
|
|
13594
|
+
if (wantsMatching && wantsPrivate) return [Q8.or(byLevel, unresolved)];
|
|
13595
|
+
if (wantsMatching) {
|
|
13596
|
+
return [Q8.or(byLevel, Q8.and(unresolved, Q8.where("scope", Q8.oneOf(published))))];
|
|
13597
|
+
}
|
|
13598
|
+
if (wantsPrivate) {
|
|
13599
|
+
return [
|
|
13600
|
+
Q8.or(
|
|
13601
|
+
byLevel,
|
|
13602
|
+
Q8.and(unresolved, Q8.or(Q8.where("scope", null), Q8.where("scope", Q8.notIn(published))))
|
|
13603
|
+
)
|
|
13604
|
+
];
|
|
13605
|
+
}
|
|
13606
|
+
return [byLevel];
|
|
13607
|
+
}
|
|
13608
|
+
function isOwnedByCtxUser(ctx, record2) {
|
|
13609
|
+
return ctx.userId === void 0 || record2.userId === ctx.userId;
|
|
13479
13610
|
}
|
|
13480
13611
|
function baseVaultConditions(ctx, options) {
|
|
13481
13612
|
return [
|
|
@@ -13517,6 +13648,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
13517
13648
|
uniqueId: memory.id,
|
|
13518
13649
|
content: memory.content,
|
|
13519
13650
|
scope: memory.scope,
|
|
13651
|
+
kind: memory.kind ?? null,
|
|
13652
|
+
kindValue: memory.kindValue ?? null,
|
|
13653
|
+
level: resolveMemoryLevel(memory.level, memory.scope),
|
|
13520
13654
|
folderId: memory.folderId ?? null,
|
|
13521
13655
|
userId: memory.userId ?? null,
|
|
13522
13656
|
embedding: memory.embedding ?? null,
|
|
@@ -13555,42 +13689,48 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
13555
13689
|
}
|
|
13556
13690
|
return raw;
|
|
13557
13691
|
}
|
|
13558
|
-
function populateNewVaultMemory(
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13563
|
-
|
|
13692
|
+
function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue) {
|
|
13693
|
+
const { level, scope } = resolveCreateLevel(opts);
|
|
13694
|
+
record2._setRaw("content", encryptedContent);
|
|
13695
|
+
record2._setRaw("scope", scope);
|
|
13696
|
+
record2._setRaw("level", level);
|
|
13697
|
+
record2._setRaw("kind", opts.kind ?? null);
|
|
13698
|
+
record2._setRaw("kind_value", encryptedKindValue ?? null);
|
|
13699
|
+
record2._setRaw("folder_id", opts.folderId ?? null);
|
|
13700
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
13701
|
+
record2._setRaw("is_deleted", false);
|
|
13564
13702
|
if (opts.embedding !== void 0) {
|
|
13565
|
-
|
|
13566
|
-
|
|
13703
|
+
record2._setRaw("embedding", opts.embedding);
|
|
13704
|
+
record2._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
13567
13705
|
}
|
|
13568
13706
|
if (opts.sourceChunkIds !== void 0) {
|
|
13569
|
-
|
|
13707
|
+
record2._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
|
|
13570
13708
|
}
|
|
13571
|
-
|
|
13572
|
-
|
|
13709
|
+
record2._setRaw("proof_count", opts.proofCount ?? 1);
|
|
13710
|
+
record2._setRaw("source", opts.source ?? "manual");
|
|
13573
13711
|
if (opts.eventTime) {
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13712
|
+
record2._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
13713
|
+
record2._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
13714
|
+
record2._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
13577
13715
|
}
|
|
13578
13716
|
if (opts.factType !== void 0) {
|
|
13579
|
-
|
|
13717
|
+
record2._setRaw("fact_type", opts.factType);
|
|
13580
13718
|
}
|
|
13581
13719
|
if (opts.trustTier !== void 0) {
|
|
13582
|
-
|
|
13720
|
+
record2._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
13583
13721
|
}
|
|
13584
|
-
|
|
13585
|
-
|
|
13722
|
+
record2._setRaw("visibility", opts.visibility ?? "private");
|
|
13723
|
+
record2._setRaw(
|
|
13586
13724
|
"published_at",
|
|
13587
13725
|
opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
|
|
13588
13726
|
);
|
|
13589
13727
|
if (opts.geohash !== void 0) {
|
|
13590
|
-
|
|
13728
|
+
record2._setRaw("geohash", opts.geohash);
|
|
13591
13729
|
}
|
|
13592
13730
|
}
|
|
13593
13731
|
async function createVaultMemoryOp(ctx, opts) {
|
|
13732
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
13733
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
13594
13734
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
13595
13735
|
opts.content,
|
|
13596
13736
|
ctx.walletAddress,
|
|
@@ -13601,13 +13741,15 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
13601
13741
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
13602
13742
|
throw new Error("Memory source is no longer eligible");
|
|
13603
13743
|
return ctx.vaultMemoryCollection.create(
|
|
13604
|
-
(
|
|
13744
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13605
13745
|
);
|
|
13606
13746
|
});
|
|
13607
13747
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
13608
13748
|
}
|
|
13609
13749
|
async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
13610
13750
|
if (!targetId) return { created: null, retired: false };
|
|
13751
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
13752
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
13611
13753
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
13612
13754
|
opts.content,
|
|
13613
13755
|
ctx.walletAddress,
|
|
@@ -13624,9 +13766,10 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
13624
13766
|
} catch {
|
|
13625
13767
|
return;
|
|
13626
13768
|
}
|
|
13627
|
-
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target))
|
|
13769
|
+
if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
|
|
13770
|
+
return;
|
|
13628
13771
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
13629
|
-
(
|
|
13772
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13630
13773
|
);
|
|
13631
13774
|
await target.update((r) => {
|
|
13632
13775
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -13690,6 +13833,10 @@ async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
|
|
|
13690
13833
|
}
|
|
13691
13834
|
async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
13692
13835
|
if (optionsArray.length === 0) return [];
|
|
13836
|
+
for (const opts of optionsArray) assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
13837
|
+
const encryptedKindValues = await Promise.all(
|
|
13838
|
+
optionsArray.map((opts) => encryptKindValue(ctx, opts.kindValue))
|
|
13839
|
+
);
|
|
13693
13840
|
const encryptedContents = await Promise.all(
|
|
13694
13841
|
optionsArray.map(async (opts) => {
|
|
13695
13842
|
if (ctx.walletAddress && ctx.signMessage) {
|
|
@@ -13708,7 +13855,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13708
13855
|
throw new Error("Memory source is no longer eligible");
|
|
13709
13856
|
const prepared = optionsArray.map(
|
|
13710
13857
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
13711
|
-
(
|
|
13858
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
13712
13859
|
)
|
|
13713
13860
|
);
|
|
13714
13861
|
await ctx.database.batch(...prepared);
|
|
@@ -13716,16 +13863,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13716
13863
|
});
|
|
13717
13864
|
return Promise.all(
|
|
13718
13865
|
created.map(
|
|
13719
|
-
(
|
|
13866
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
13720
13867
|
)
|
|
13721
13868
|
);
|
|
13722
13869
|
}
|
|
13723
13870
|
async function getVaultMemoryOp(ctx, id) {
|
|
13724
13871
|
try {
|
|
13725
|
-
const
|
|
13726
|
-
if (
|
|
13872
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
13873
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
13727
13874
|
return vaultMemoryToStored(
|
|
13728
|
-
|
|
13875
|
+
record2,
|
|
13729
13876
|
ctx.walletAddress,
|
|
13730
13877
|
ctx.signMessage,
|
|
13731
13878
|
ctx.embeddedWalletSigner
|
|
@@ -13751,6 +13898,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
13751
13898
|
uniqueId: raw.id,
|
|
13752
13899
|
content: raw.content ?? "",
|
|
13753
13900
|
scope: raw.scope ?? "",
|
|
13901
|
+
kind: raw.kind ?? null,
|
|
13902
|
+
kindValue: raw.kind_value ?? null,
|
|
13903
|
+
level: resolveMemoryLevel(raw.level, raw.scope),
|
|
13754
13904
|
folderId: raw.folder_id ?? null,
|
|
13755
13905
|
userId: raw.user_id ?? null,
|
|
13756
13906
|
embedding: raw.embedding ?? null,
|
|
@@ -13783,17 +13933,19 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
13783
13933
|
};
|
|
13784
13934
|
}
|
|
13785
13935
|
async function vaultMemoryRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner) {
|
|
13786
|
-
const
|
|
13936
|
+
const stored2 = vaultMemoryRawToStoredRaw(raw);
|
|
13787
13937
|
if (walletAddress) {
|
|
13788
|
-
return decryptVaultMemoryFields(
|
|
13938
|
+
return decryptVaultMemoryFields(stored2, walletAddress, signMessage, embeddedWalletSigner);
|
|
13789
13939
|
}
|
|
13790
|
-
return
|
|
13940
|
+
return stored2;
|
|
13791
13941
|
}
|
|
13792
13942
|
async function getAllVaultMemoriesOp(ctx, options) {
|
|
13793
13943
|
const conditions = [
|
|
13794
13944
|
...baseVaultConditions(ctx, options),
|
|
13795
13945
|
...options?.scopes?.length ? [Q8.where("scope", Q8.oneOf(options.scopes))] : [],
|
|
13796
13946
|
...visibilityConditions(options?.visibility),
|
|
13947
|
+
...levelConditions(options?.levels),
|
|
13948
|
+
...options?.kinds?.length ? [Q8.where("kind", Q8.oneOf(options.kinds))] : [],
|
|
13797
13949
|
...options?.folderId !== void 0 ? [Q8.where("folder_id", options.folderId)] : [],
|
|
13798
13950
|
...options?.factTypes?.length ? [Q8.where("fact_type", Q8.oneOf(options.factTypes))] : [],
|
|
13799
13951
|
Q8.sortBy(options?.since ? "updated_at" : "created_at", Q8.desc),
|
|
@@ -13939,13 +14091,13 @@ async function getVaultMemoriesByIdsOp(ctx, ids, options) {
|
|
|
13939
14091
|
async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
13940
14092
|
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
|
|
13941
14093
|
return mapInBatches(results, async (raw) => {
|
|
13942
|
-
const
|
|
14094
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
13943
14095
|
raw,
|
|
13944
14096
|
ctx.walletAddress,
|
|
13945
14097
|
ctx.signMessage,
|
|
13946
14098
|
ctx.embeddedWalletSigner
|
|
13947
14099
|
);
|
|
13948
|
-
return
|
|
14100
|
+
return stored2.content;
|
|
13949
14101
|
});
|
|
13950
14102
|
}
|
|
13951
14103
|
async function countActiveVaultMemoriesOp(ctx) {
|
|
@@ -13960,6 +14112,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13960
14112
|
try {
|
|
13961
14113
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
13962
14114
|
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
14115
|
+
if (opts.freeFormOnly && isKinded(probe)) return null;
|
|
14116
|
+
const levelAfter = (current) => {
|
|
14117
|
+
if (opts.level !== void 0) return opts.level;
|
|
14118
|
+
if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
|
|
14119
|
+
return levelForScopeChange(current, opts.scope);
|
|
14120
|
+
};
|
|
14121
|
+
assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
|
|
14122
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
13963
14123
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
13964
14124
|
opts.content,
|
|
13965
14125
|
ctx.walletAddress,
|
|
@@ -13967,30 +14127,43 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13967
14127
|
ctx.embeddedWalletSigner
|
|
13968
14128
|
) : opts.content;
|
|
13969
14129
|
let stale = false;
|
|
13970
|
-
const
|
|
13971
|
-
const originalUpdatedAt =
|
|
14130
|
+
const record2 = probe;
|
|
14131
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13972
14132
|
await ctx.database.write(async () => {
|
|
13973
14133
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
13974
14134
|
throw new Error("Memory source is no longer eligible");
|
|
13975
|
-
if (
|
|
14135
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
13976
14136
|
stale = true;
|
|
13977
14137
|
return;
|
|
13978
14138
|
}
|
|
14139
|
+
const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
|
|
14140
|
+
const nextLevel = levelAfter(record2);
|
|
14141
|
+
assertValidKindLevel(nextKind, nextLevel);
|
|
13979
14142
|
let observedSources = [];
|
|
13980
14143
|
let replayedObservation = false;
|
|
13981
14144
|
if (opts.observationSourceIds?.length) {
|
|
13982
14145
|
try {
|
|
13983
|
-
const parsed = JSON.parse(
|
|
14146
|
+
const parsed = JSON.parse(record2.sourceChunkIds ?? "[]");
|
|
13984
14147
|
if (Array.isArray(parsed))
|
|
13985
14148
|
observedSources = parsed.filter((id2) => typeof id2 === "string");
|
|
13986
14149
|
} catch {
|
|
13987
14150
|
}
|
|
13988
14151
|
replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
|
|
13989
14152
|
}
|
|
13990
|
-
await
|
|
14153
|
+
await record2.update((r) => {
|
|
13991
14154
|
r._setRaw("content", encryptedContent);
|
|
13992
|
-
if (opts.
|
|
14155
|
+
if (opts.level !== void 0) {
|
|
14156
|
+
r._setRaw("level", nextLevel);
|
|
14157
|
+
r._setRaw("scope", scopeForLevel(nextLevel));
|
|
14158
|
+
} else if (opts.scope !== void 0) {
|
|
13993
14159
|
r._setRaw("scope", opts.scope);
|
|
14160
|
+
r._setRaw("level", nextLevel);
|
|
14161
|
+
}
|
|
14162
|
+
if (opts.kind !== void 0) {
|
|
14163
|
+
r._setRaw("kind", opts.kind);
|
|
14164
|
+
}
|
|
14165
|
+
if (encryptedKindValue !== void 0) {
|
|
14166
|
+
r._setRaw("kind_value", encryptedKindValue);
|
|
13994
14167
|
}
|
|
13995
14168
|
if (opts.folderId !== void 0) {
|
|
13996
14169
|
r._setRaw("folder_id", opts.folderId);
|
|
@@ -14044,12 +14217,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
14044
14217
|
});
|
|
14045
14218
|
if (stale) return null;
|
|
14046
14219
|
return vaultMemoryToStored(
|
|
14047
|
-
|
|
14220
|
+
record2,
|
|
14048
14221
|
ctx.walletAddress,
|
|
14049
14222
|
ctx.signMessage,
|
|
14050
14223
|
ctx.embeddedWalletSigner
|
|
14051
14224
|
);
|
|
14052
|
-
} catch {
|
|
14225
|
+
} catch (err) {
|
|
14226
|
+
if (err instanceof MemoryLevelError) throw err;
|
|
14053
14227
|
return null;
|
|
14054
14228
|
}
|
|
14055
14229
|
}
|
|
@@ -14058,21 +14232,21 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
14058
14232
|
if (!entityCtx) {
|
|
14059
14233
|
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
14060
14234
|
}
|
|
14061
|
-
let
|
|
14235
|
+
let record2;
|
|
14062
14236
|
try {
|
|
14063
|
-
|
|
14237
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
14064
14238
|
} catch {
|
|
14065
14239
|
return null;
|
|
14066
14240
|
}
|
|
14067
|
-
if (
|
|
14241
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
14068
14242
|
let stale = false;
|
|
14069
|
-
const originalUpdatedAt =
|
|
14243
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14070
14244
|
await ctx.database.write(async (writer) => {
|
|
14071
|
-
if (
|
|
14245
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14072
14246
|
stale = true;
|
|
14073
14247
|
return;
|
|
14074
14248
|
}
|
|
14075
|
-
await
|
|
14249
|
+
await record2.update((r) => {
|
|
14076
14250
|
r._setRaw("topics_user_managed", true);
|
|
14077
14251
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
14078
14252
|
});
|
|
@@ -14096,25 +14270,25 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
14096
14270
|
);
|
|
14097
14271
|
});
|
|
14098
14272
|
if (stale) return null;
|
|
14099
|
-
return vaultMemoryToStored(
|
|
14273
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
14100
14274
|
}
|
|
14101
14275
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
14102
|
-
let
|
|
14276
|
+
let record2;
|
|
14103
14277
|
try {
|
|
14104
|
-
|
|
14278
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
14105
14279
|
} catch {
|
|
14106
14280
|
return false;
|
|
14107
14281
|
}
|
|
14108
|
-
if (
|
|
14109
|
-
const originalUpdatedAt =
|
|
14282
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14283
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14110
14284
|
let cleared = false;
|
|
14111
14285
|
await ctx.database.write(async () => {
|
|
14112
|
-
if (options?.unlessTopicsRecorded && parseTopics(
|
|
14286
|
+
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
14113
14287
|
cleared = true;
|
|
14114
|
-
await
|
|
14288
|
+
await record2.update((r) => {
|
|
14115
14289
|
r._setRaw("topics_user_managed", false);
|
|
14116
14290
|
r._setRaw("topics_extracted_version", null);
|
|
14117
|
-
if (
|
|
14291
|
+
if (record2.topicsExtractedAt === null) {
|
|
14118
14292
|
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
14119
14293
|
}
|
|
14120
14294
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -14123,22 +14297,22 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
14123
14297
|
return cleared;
|
|
14124
14298
|
}
|
|
14125
14299
|
async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
14126
|
-
let
|
|
14300
|
+
let record2;
|
|
14127
14301
|
try {
|
|
14128
|
-
|
|
14302
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14129
14303
|
} catch {
|
|
14130
14304
|
return null;
|
|
14131
14305
|
}
|
|
14132
|
-
if (
|
|
14306
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
14133
14307
|
let stale = false;
|
|
14134
14308
|
await ctx.database.write(async () => {
|
|
14135
|
-
if (
|
|
14309
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14136
14310
|
stale = true;
|
|
14137
14311
|
return;
|
|
14138
14312
|
}
|
|
14139
|
-
const currentUpdatedAt =
|
|
14140
|
-
const currentPublishedAt =
|
|
14141
|
-
await
|
|
14313
|
+
const currentUpdatedAt = record2.updatedAt.getTime();
|
|
14314
|
+
const currentPublishedAt = record2.publishedAt ?? null;
|
|
14315
|
+
await record2.update((r) => {
|
|
14142
14316
|
r._setRaw("visibility", opts.visibility);
|
|
14143
14317
|
if (opts.visibility === "private") {
|
|
14144
14318
|
r._setRaw("published_at", null);
|
|
@@ -14152,19 +14326,19 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
14152
14326
|
});
|
|
14153
14327
|
});
|
|
14154
14328
|
if (stale) return null;
|
|
14155
|
-
return vaultMemoryToStored(
|
|
14329
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
14156
14330
|
}
|
|
14157
14331
|
async function deleteVaultMemoryOp(ctx, id) {
|
|
14158
14332
|
try {
|
|
14159
|
-
const
|
|
14160
|
-
if (
|
|
14333
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14334
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14161
14335
|
let stale = false;
|
|
14162
14336
|
await ctx.database.write(async () => {
|
|
14163
|
-
if (
|
|
14337
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14164
14338
|
stale = true;
|
|
14165
14339
|
return;
|
|
14166
14340
|
}
|
|
14167
|
-
await
|
|
14341
|
+
await record2.update((r) => {
|
|
14168
14342
|
r._setRaw("is_deleted", true);
|
|
14169
14343
|
});
|
|
14170
14344
|
});
|
|
@@ -14183,8 +14357,9 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
14183
14357
|
async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
14184
14358
|
if (id === supersededById) return false;
|
|
14185
14359
|
try {
|
|
14186
|
-
const
|
|
14187
|
-
if (
|
|
14360
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14361
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14362
|
+
if (isKinded(record2)) return false;
|
|
14188
14363
|
let successor;
|
|
14189
14364
|
try {
|
|
14190
14365
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -14198,7 +14373,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
14198
14373
|
await ctx.database.write(async () => {
|
|
14199
14374
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
14200
14375
|
throw new Error("Memory source is no longer eligible");
|
|
14201
|
-
if (
|
|
14376
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
14202
14377
|
stale = true;
|
|
14203
14378
|
return;
|
|
14204
14379
|
}
|
|
@@ -14206,7 +14381,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
14206
14381
|
stale = true;
|
|
14207
14382
|
return;
|
|
14208
14383
|
}
|
|
14209
|
-
await
|
|
14384
|
+
await record2.update((r) => {
|
|
14210
14385
|
r._setRaw("superseded_by", supersededById);
|
|
14211
14386
|
r._setRaw("superseded_at", Date.now());
|
|
14212
14387
|
});
|
|
@@ -14225,7 +14400,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
14225
14400
|
const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
|
|
14226
14401
|
return mapInBatches(
|
|
14227
14402
|
results,
|
|
14228
|
-
(
|
|
14403
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
14229
14404
|
);
|
|
14230
14405
|
}
|
|
14231
14406
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
@@ -14367,17 +14542,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
14367
14542
|
}
|
|
14368
14543
|
}
|
|
14369
14544
|
const eligible = records.filter(
|
|
14370
|
-
(
|
|
14545
|
+
(record2) => !record2.isDeleted && isOwnedByCtxUser(ctx, record2) && !record2.topicsUserManaged
|
|
14371
14546
|
);
|
|
14372
|
-
const prepared = eligible.map((
|
|
14373
|
-
const originalUpdatedAt =
|
|
14374
|
-
return
|
|
14547
|
+
const prepared = eligible.map((record2) => {
|
|
14548
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14549
|
+
return record2.prepareUpdate((r) => {
|
|
14375
14550
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
14376
14551
|
r._setRaw("topics_extracted_version", version);
|
|
14377
14552
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
14378
14553
|
});
|
|
14379
14554
|
});
|
|
14380
|
-
for (const
|
|
14555
|
+
for (const record2 of eligible) stamped.push(record2.id);
|
|
14381
14556
|
if (prepared.length > 0) await ctx.database.batch(...prepared);
|
|
14382
14557
|
});
|
|
14383
14558
|
}
|
|
@@ -14392,14 +14567,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14392
14567
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
14393
14568
|
try {
|
|
14394
14569
|
await ctx.database.write(async (writer) => {
|
|
14395
|
-
let
|
|
14570
|
+
let record2;
|
|
14396
14571
|
try {
|
|
14397
|
-
|
|
14572
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14398
14573
|
} catch {
|
|
14399
14574
|
return;
|
|
14400
14575
|
}
|
|
14401
|
-
if (
|
|
14402
|
-
const topics = parseTopics(
|
|
14576
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14577
|
+
const topics = parseTopics(record2.topics);
|
|
14403
14578
|
if (topics === null) return;
|
|
14404
14579
|
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
|
|
14405
14580
|
relinked.push(id);
|
|
@@ -14424,20 +14599,20 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14424
14599
|
await ctx.database.write(async () => {
|
|
14425
14600
|
const writes = [];
|
|
14426
14601
|
for (const id of chunkIds) {
|
|
14427
|
-
let
|
|
14602
|
+
let record2;
|
|
14428
14603
|
try {
|
|
14429
|
-
|
|
14604
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14430
14605
|
} catch {
|
|
14431
14606
|
continue;
|
|
14432
14607
|
}
|
|
14433
|
-
if (
|
|
14434
|
-
if (parseTopics(
|
|
14608
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) continue;
|
|
14609
|
+
if (parseTopics(record2.topics) !== null) continue;
|
|
14435
14610
|
const links = await entityCtx.memoryEntityCollection.query(Q8.where("memory_id", id)).unsafeFetchRaw();
|
|
14436
14611
|
const entityIds = links.map((l) => String(l.entity_id));
|
|
14437
14612
|
if (entityIds.length === 0) continue;
|
|
14438
14613
|
const entities = await entityCtx.entityCollection.query(Q8.where("id", Q8.oneOf(entityIds))).fetch();
|
|
14439
14614
|
if (entities.length === 0) continue;
|
|
14440
|
-
const source =
|
|
14615
|
+
const source = record2.topicsUserManaged ? "user" : "auto";
|
|
14441
14616
|
const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
|
|
14442
14617
|
if (write) writes.push(write);
|
|
14443
14618
|
}
|
|
@@ -14455,7 +14630,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
14455
14630
|
if (records.length === 0) return 0;
|
|
14456
14631
|
await ctx.database.write(async () => {
|
|
14457
14632
|
const prepared = records.map(
|
|
14458
|
-
(
|
|
14633
|
+
(record2) => record2.prepareUpdate((r) => {
|
|
14459
14634
|
r._setRaw("is_deleted", true);
|
|
14460
14635
|
})
|
|
14461
14636
|
);
|
|
@@ -14485,7 +14660,10 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
14485
14660
|
}
|
|
14486
14661
|
async function getDecayCandidatesRawOp(ctx) {
|
|
14487
14662
|
assertVaultScopeForSweep(ctx);
|
|
14488
|
-
const results = await ctx.vaultMemoryCollection.query(
|
|
14663
|
+
const results = await ctx.vaultMemoryCollection.query(
|
|
14664
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
14665
|
+
Q8.where("kind", null)
|
|
14666
|
+
).unsafeFetchRaw();
|
|
14489
14667
|
return results.map((raw) => ({
|
|
14490
14668
|
uniqueId: raw.id,
|
|
14491
14669
|
factType: raw.fact_type ?? null,
|
|
@@ -14500,20 +14678,20 @@ async function getDecayCandidatesRawOp(ctx) {
|
|
|
14500
14678
|
}
|
|
14501
14679
|
async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
14502
14680
|
try {
|
|
14503
|
-
const
|
|
14504
|
-
if (
|
|
14681
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14682
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14505
14683
|
let stale = false;
|
|
14506
14684
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
14507
14685
|
await ctx.database.write(async () => {
|
|
14508
|
-
if (
|
|
14686
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
14509
14687
|
stale = true;
|
|
14510
14688
|
return;
|
|
14511
14689
|
}
|
|
14512
|
-
if (opts?.expectedUpdatedAt !== void 0 &&
|
|
14690
|
+
if (opts?.expectedUpdatedAt !== void 0 && record2.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record2.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
|
|
14513
14691
|
stale = true;
|
|
14514
14692
|
return;
|
|
14515
14693
|
}
|
|
14516
|
-
await
|
|
14694
|
+
await record2.update((r) => {
|
|
14517
14695
|
r._setRaw("archived_at", archivedAtValue);
|
|
14518
14696
|
});
|
|
14519
14697
|
});
|
|
@@ -14524,15 +14702,15 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
14524
14702
|
}
|
|
14525
14703
|
async function restoreVaultMemoryOp(ctx, id) {
|
|
14526
14704
|
try {
|
|
14527
|
-
const
|
|
14528
|
-
if (
|
|
14705
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14706
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14529
14707
|
let stale = false;
|
|
14530
14708
|
await ctx.database.write(async () => {
|
|
14531
|
-
if (
|
|
14709
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14532
14710
|
stale = true;
|
|
14533
14711
|
return;
|
|
14534
14712
|
}
|
|
14535
|
-
await
|
|
14713
|
+
await record2.update((r) => {
|
|
14536
14714
|
r._setRaw("archived_at", null);
|
|
14537
14715
|
});
|
|
14538
14716
|
});
|
|
@@ -14543,17 +14721,17 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
14543
14721
|
}
|
|
14544
14722
|
async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
14545
14723
|
try {
|
|
14546
|
-
const
|
|
14547
|
-
if (
|
|
14724
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14725
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14548
14726
|
const now = opts.now ?? Date.now();
|
|
14549
14727
|
let stale = false;
|
|
14550
14728
|
await ctx.database.write(async () => {
|
|
14551
|
-
const archivedAt =
|
|
14552
|
-
if (
|
|
14729
|
+
const archivedAt = record2.archivedAt;
|
|
14730
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
14553
14731
|
stale = true;
|
|
14554
14732
|
return;
|
|
14555
14733
|
}
|
|
14556
|
-
await
|
|
14734
|
+
await record2.update((r) => {
|
|
14557
14735
|
r._setRaw("is_deleted", true);
|
|
14558
14736
|
});
|
|
14559
14737
|
});
|
|
@@ -14571,14 +14749,14 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
14571
14749
|
}
|
|
14572
14750
|
async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel, expected) {
|
|
14573
14751
|
try {
|
|
14574
|
-
const
|
|
14575
|
-
if (
|
|
14576
|
-
const readUpdatedAt =
|
|
14577
|
-
const readStoredContent =
|
|
14752
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14753
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14754
|
+
const readUpdatedAt = record2.updatedAt.getTime();
|
|
14755
|
+
const readStoredContent = record2._getRaw("content");
|
|
14578
14756
|
if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
|
|
14579
14757
|
if (expected?.content !== void 0) {
|
|
14580
14758
|
const current = await vaultMemoryToStored(
|
|
14581
|
-
|
|
14759
|
+
record2,
|
|
14582
14760
|
ctx.walletAddress,
|
|
14583
14761
|
ctx.signMessage,
|
|
14584
14762
|
ctx.embeddedWalletSigner
|
|
@@ -14587,11 +14765,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
14587
14765
|
}
|
|
14588
14766
|
let written = false;
|
|
14589
14767
|
await ctx.database.write(async () => {
|
|
14590
|
-
if (
|
|
14591
|
-
const originalUpdatedAt =
|
|
14592
|
-
if (originalUpdatedAt !== readUpdatedAt ||
|
|
14768
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14769
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14770
|
+
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
14593
14771
|
return;
|
|
14594
|
-
await
|
|
14772
|
+
await record2.update((r) => {
|
|
14595
14773
|
r._setRaw("embedding", embedding);
|
|
14596
14774
|
r._setRaw("embedding_model", embeddingModel);
|
|
14597
14775
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -14606,8 +14784,8 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
14606
14784
|
function normalizeForDedupe(content) {
|
|
14607
14785
|
return content.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
14608
14786
|
}
|
|
14609
|
-
async function findQuarantinedDuplicateOp(ctx, content,
|
|
14610
|
-
const wanted = [...new Set(
|
|
14787
|
+
async function findQuarantinedDuplicateOp(ctx, content, sourceIds2, where) {
|
|
14788
|
+
const wanted = [...new Set(sourceIds2)].sort().join("\0");
|
|
14611
14789
|
const target = normalizeForDedupe(content);
|
|
14612
14790
|
const rows = await ctx.vaultMemoryCollection.query(
|
|
14613
14791
|
Q8.where("trust_tier", "quarantined"),
|
|
@@ -14626,13 +14804,13 @@ async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
|
|
|
14626
14804
|
if (!Array.isArray(ids)) continue;
|
|
14627
14805
|
const key = [...new Set(ids.filter((id) => typeof id === "string"))].sort().join("\0");
|
|
14628
14806
|
if (key !== wanted) continue;
|
|
14629
|
-
const
|
|
14807
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
14630
14808
|
raw,
|
|
14631
14809
|
ctx.walletAddress,
|
|
14632
14810
|
ctx.signMessage,
|
|
14633
14811
|
ctx.embeddedWalletSigner
|
|
14634
14812
|
);
|
|
14635
|
-
if (normalizeForDedupe(
|
|
14813
|
+
if (normalizeForDedupe(stored2.content) === target) return stored2.uniqueId;
|
|
14636
14814
|
}
|
|
14637
14815
|
return null;
|
|
14638
14816
|
}
|
|
@@ -14741,25 +14919,26 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
14741
14919
|
inserted = writable.length;
|
|
14742
14920
|
if (writable.length === 0) return;
|
|
14743
14921
|
const prepared = writable.map(
|
|
14744
|
-
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((
|
|
14745
|
-
|
|
14746
|
-
|
|
14747
|
-
|
|
14748
|
-
|
|
14749
|
-
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14922
|
+
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record2) => {
|
|
14923
|
+
record2._raw.id = row.memoryId;
|
|
14924
|
+
record2._setRaw("content", content);
|
|
14925
|
+
record2._setRaw("scope", "shared");
|
|
14926
|
+
record2._setRaw("level", "matching");
|
|
14927
|
+
record2._setRaw("folder_id", null);
|
|
14928
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
14929
|
+
record2._setRaw("is_deleted", false);
|
|
14930
|
+
record2._setRaw("proof_count", 1);
|
|
14931
|
+
record2._setRaw("source", SOURCE_PHOTO);
|
|
14932
|
+
record2._setRaw(
|
|
14754
14933
|
"media",
|
|
14755
14934
|
row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
|
|
14756
14935
|
);
|
|
14757
|
-
|
|
14758
|
-
|
|
14936
|
+
record2._setRaw("visibility", "public");
|
|
14937
|
+
record2._setRaw("published_at", now);
|
|
14759
14938
|
if (row.eventTime) {
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14939
|
+
record2._setRaw("event_time_start", row.eventTime.start ?? null);
|
|
14940
|
+
record2._setRaw("event_time_end", row.eventTime.end ?? null);
|
|
14941
|
+
record2._setRaw("event_time_kind", row.eventTime.kind ?? null);
|
|
14763
14942
|
}
|
|
14764
14943
|
})
|
|
14765
14944
|
);
|
|
@@ -15580,11 +15759,11 @@ function folderToStored(folder) {
|
|
|
15580
15759
|
}
|
|
15581
15760
|
async function createVaultFolderOp(ctx, opts) {
|
|
15582
15761
|
const created = await ctx.database.write(async () => {
|
|
15583
|
-
return ctx.vaultFolderCollection.create((
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15762
|
+
return ctx.vaultFolderCollection.create((record2) => {
|
|
15763
|
+
record2._setRaw("name", opts.name);
|
|
15764
|
+
record2._setRaw("scope", opts.scope ?? "private");
|
|
15765
|
+
record2._setRaw("is_system", opts.isSystem ?? false);
|
|
15766
|
+
record2._setRaw("is_deleted", false);
|
|
15588
15767
|
});
|
|
15589
15768
|
});
|
|
15590
15769
|
return folderToStored(created);
|
|
@@ -15595,14 +15774,14 @@ async function getAllVaultFoldersOp(ctx) {
|
|
|
15595
15774
|
}
|
|
15596
15775
|
async function updateVaultFolderOp(ctx, id, opts) {
|
|
15597
15776
|
try {
|
|
15598
|
-
const
|
|
15599
|
-
if (
|
|
15600
|
-
const scopeChanged = opts.scope !== void 0 && opts.scope !==
|
|
15777
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
15778
|
+
if (record2.isDeleted) return null;
|
|
15779
|
+
const scopeChanged = opts.scope !== void 0 && opts.scope !== record2.scope;
|
|
15601
15780
|
const updated = await ctx.database.write(async () => {
|
|
15602
15781
|
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q13.where("folder_id", id), Q13.where("is_deleted", false)).fetch() : [];
|
|
15603
15782
|
const updates = [];
|
|
15604
15783
|
updates.push(
|
|
15605
|
-
|
|
15784
|
+
record2.prepareUpdate((r) => {
|
|
15606
15785
|
if (opts.name !== void 0) r._setRaw("name", opts.name);
|
|
15607
15786
|
if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
|
|
15608
15787
|
})
|
|
@@ -15610,6 +15789,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
15610
15789
|
for (const memory of memories) {
|
|
15611
15790
|
updates.push(
|
|
15612
15791
|
memory.prepareUpdate((r) => {
|
|
15792
|
+
r._setRaw("level", levelForScopeChange(r, opts.scope));
|
|
15613
15793
|
r._setRaw("scope", opts.scope);
|
|
15614
15794
|
})
|
|
15615
15795
|
);
|
|
@@ -15624,17 +15804,18 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
15624
15804
|
}
|
|
15625
15805
|
async function deleteVaultFolderOp(ctx, id) {
|
|
15626
15806
|
try {
|
|
15627
|
-
const
|
|
15628
|
-
if (
|
|
15807
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
15808
|
+
if (record2.isDeleted) return false;
|
|
15629
15809
|
await ctx.database.write(async () => {
|
|
15630
15810
|
const memories = await ctx.vaultMemoryCollection.query(Q13.where("folder_id", id), Q13.where("is_deleted", false)).fetch();
|
|
15631
15811
|
const preparedMemories = memories.map(
|
|
15632
15812
|
(memory) => memory.prepareUpdate((r) => {
|
|
15633
15813
|
r._setRaw("folder_id", null);
|
|
15814
|
+
r._setRaw("level", levelForScopeChange(r, "private"));
|
|
15634
15815
|
r._setRaw("scope", "private");
|
|
15635
15816
|
})
|
|
15636
15817
|
);
|
|
15637
|
-
const preparedFolder =
|
|
15818
|
+
const preparedFolder = record2.prepareUpdate((r) => {
|
|
15638
15819
|
r._setRaw("is_deleted", true);
|
|
15639
15820
|
});
|
|
15640
15821
|
await ctx.database.batch(...preparedMemories, preparedFolder);
|
|
@@ -15667,6 +15848,7 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
15667
15848
|
const prepared = memories.map(
|
|
15668
15849
|
(memory) => memory.prepareUpdate((r) => {
|
|
15669
15850
|
r._setRaw("folder_id", folderId);
|
|
15851
|
+
r._setRaw("level", levelForScopeChange(r, targetScope));
|
|
15670
15852
|
r._setRaw("scope", targetScope);
|
|
15671
15853
|
})
|
|
15672
15854
|
);
|
|
@@ -15680,11 +15862,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
15680
15862
|
}
|
|
15681
15863
|
async function updateVaultFolderContextOp(ctx, id, context) {
|
|
15682
15864
|
try {
|
|
15683
|
-
const
|
|
15684
|
-
if (
|
|
15865
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
15866
|
+
if (record2.isDeleted) return null;
|
|
15685
15867
|
const updated = await ctx.database.write(async () => {
|
|
15686
15868
|
await ctx.database.batch(
|
|
15687
|
-
|
|
15869
|
+
record2.prepareUpdate((r) => {
|
|
15688
15870
|
r._setRaw("context", context);
|
|
15689
15871
|
})
|
|
15690
15872
|
);
|
|
@@ -17741,7 +17923,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
17741
17923
|
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
17742
17924
|
let subEmbeddings;
|
|
17743
17925
|
try {
|
|
17744
|
-
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
17926
|
+
subEmbeddings = prepared.facetEmbeddings ?? await generateEmbeddings(facetQueries, embeddingOptions);
|
|
17745
17927
|
} catch (err) {
|
|
17746
17928
|
getLogger().warn(
|
|
17747
17929
|
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
@@ -17926,6 +18108,35 @@ var DEFAULT_SCOPE = "private";
|
|
|
17926
18108
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
17927
18109
|
var DEFAULT_CONSOLIDATE_TOP_K = 20;
|
|
17928
18110
|
async function retain(content, ctx, options = {}) {
|
|
18111
|
+
return retainWithPersistence(
|
|
18112
|
+
content,
|
|
18113
|
+
{
|
|
18114
|
+
embeddingOptions: ctx.embeddingOptions,
|
|
18115
|
+
vaultCache: ctx.vaultCache,
|
|
18116
|
+
persistence: {
|
|
18117
|
+
prepare: (query, searchOptions) => prepareVaultCandidates(
|
|
18118
|
+
query,
|
|
18119
|
+
ctx.vaultCtx,
|
|
18120
|
+
ctx.embeddingOptions,
|
|
18121
|
+
ctx.vaultCache,
|
|
18122
|
+
searchOptions
|
|
18123
|
+
),
|
|
18124
|
+
get: (id) => getVaultMemoryOp(ctx.vaultCtx, id),
|
|
18125
|
+
tombstones: (_embedding, _model, scope, folderId) => getAllVaultMemoriesOp(ctx.vaultCtx, {
|
|
18126
|
+
includeDeleted: true,
|
|
18127
|
+
scopes: [scope],
|
|
18128
|
+
...folderId !== void 0 && { folderId }
|
|
18129
|
+
}),
|
|
18130
|
+
create: (input) => createVaultMemoryOp(ctx.vaultCtx, input),
|
|
18131
|
+
update: (id, patch) => updateVaultMemoryOp(ctx.vaultCtx, id, patch),
|
|
18132
|
+
supersede: (id, successor) => supersedeVaultMemoryOp(ctx.vaultCtx, id, successor),
|
|
18133
|
+
createSuperseding: (input, target) => createSupersedingMemoryOp(ctx.vaultCtx, input, target)
|
|
18134
|
+
}
|
|
18135
|
+
},
|
|
18136
|
+
options
|
|
18137
|
+
);
|
|
18138
|
+
}
|
|
18139
|
+
async function retainWithPersistence(content, ctx, options = {}) {
|
|
17929
18140
|
const trimmed = content.trim();
|
|
17930
18141
|
if (trimmed.length === 0) {
|
|
17931
18142
|
throw new Error("retain: content cannot be empty");
|
|
@@ -17938,19 +18149,14 @@ async function retain(content, ctx, options = {}) {
|
|
|
17938
18149
|
let supersedeContent;
|
|
17939
18150
|
let prepared;
|
|
17940
18151
|
if (enableAutoMerge) {
|
|
17941
|
-
prepared = await
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
{
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
scopes: [resolvedScope],
|
|
17950
|
-
includeArchived: true,
|
|
17951
|
-
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
17952
|
-
}
|
|
17953
|
-
);
|
|
18152
|
+
prepared = await ctx.persistence.prepare(trimmed, {
|
|
18153
|
+
limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
|
|
18154
|
+
useFusion: false,
|
|
18155
|
+
scopes: [resolvedScope],
|
|
18156
|
+
includeArchived: true,
|
|
18157
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
18158
|
+
});
|
|
18159
|
+
prepared = withoutKindedRows(prepared);
|
|
17954
18160
|
if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
|
|
17955
18161
|
throw new Error(
|
|
17956
18162
|
"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 +18187,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
17981
18187
|
);
|
|
17982
18188
|
if (matches.length > 0) {
|
|
17983
18189
|
const targetId = matches[0].uniqueId;
|
|
17984
|
-
const existing = await
|
|
18190
|
+
const existing = await ctx.persistence.get(targetId);
|
|
17985
18191
|
if (existing && !existing.supersededBy) {
|
|
17986
18192
|
const mergedSourceIds = unionStrings(
|
|
17987
18193
|
existing.sourceChunkIds ?? [],
|
|
@@ -17990,8 +18196,9 @@ async function retain(content, ctx, options = {}) {
|
|
|
17990
18196
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
17991
18197
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
17992
18198
|
const resurrect = resurrectFields(existing);
|
|
17993
|
-
const updated = await
|
|
18199
|
+
const updated = await ctx.persistence.update(targetId, {
|
|
17994
18200
|
content: existing.content,
|
|
18201
|
+
freeFormOnly: true,
|
|
17995
18202
|
proofCountIncrement: 1,
|
|
17996
18203
|
observationSourceIds: options.sourceChunkIds,
|
|
17997
18204
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -18017,7 +18224,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
18017
18224
|
}
|
|
18018
18225
|
const contentToWrite = supersedeContent ?? trimmed;
|
|
18019
18226
|
const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
|
|
18020
|
-
const
|
|
18227
|
+
const generatedEmbedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
18228
|
+
const embedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
18021
18229
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18022
18230
|
if (options.respectTombstones) {
|
|
18023
18231
|
const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
@@ -18057,8 +18265,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
18057
18265
|
};
|
|
18058
18266
|
if (supersedeTargetIds.length > 0) {
|
|
18059
18267
|
const [primaryTargetId, ...restTargetIds] = supersedeTargetIds;
|
|
18060
|
-
const { created: created2, retired } = await
|
|
18061
|
-
ctx.vaultCtx,
|
|
18268
|
+
const { created: created2, retired } = await ctx.persistence.createSuperseding(
|
|
18062
18269
|
createOpts,
|
|
18063
18270
|
primaryTargetId
|
|
18064
18271
|
);
|
|
@@ -18074,11 +18281,11 @@ async function retain(content, ctx, options = {}) {
|
|
|
18074
18281
|
for (const staleId of restTargetIds) {
|
|
18075
18282
|
let ok = false;
|
|
18076
18283
|
try {
|
|
18077
|
-
ok = await
|
|
18284
|
+
ok = await ctx.persistence.supersede(staleId, created2.uniqueId) === true;
|
|
18078
18285
|
} catch {
|
|
18079
18286
|
}
|
|
18080
18287
|
if (ok) continue;
|
|
18081
|
-
const stillLive = await
|
|
18288
|
+
const stillLive = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(staleId) : ctx.persistence.get(staleId)).catch(() => null);
|
|
18082
18289
|
if (stillLive && !stillLive.supersededBy) liveLeftovers.push(staleId);
|
|
18083
18290
|
}
|
|
18084
18291
|
if (liveLeftovers.length > 0) {
|
|
@@ -18105,7 +18312,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
18105
18312
|
`supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
|
|
18106
18313
|
);
|
|
18107
18314
|
}
|
|
18108
|
-
const created = await
|
|
18315
|
+
const created = await ctx.persistence.create(createOpts);
|
|
18109
18316
|
cacheRowVector(
|
|
18110
18317
|
ctx.vaultCache,
|
|
18111
18318
|
created.uniqueId,
|
|
@@ -18120,15 +18327,22 @@ async function retain(content, ctx, options = {}) {
|
|
|
18120
18327
|
...consolidationDecidedCreate && { consolidation: "create" }
|
|
18121
18328
|
};
|
|
18122
18329
|
}
|
|
18330
|
+
function withoutKindedRows(prepared) {
|
|
18331
|
+
const kinded = new Set(
|
|
18332
|
+
prepared.memories.filter((m) => m.kind !== null && m.kind !== void 0).map((m) => m.uniqueId)
|
|
18333
|
+
);
|
|
18334
|
+
if (kinded.size === 0) return prepared;
|
|
18335
|
+
return {
|
|
18336
|
+
...prepared,
|
|
18337
|
+
memories: prepared.memories.filter((m) => !kinded.has(m.uniqueId)),
|
|
18338
|
+
embeddedItems: prepared.embeddedItems.filter((item) => !kinded.has(item.id))
|
|
18339
|
+
};
|
|
18340
|
+
}
|
|
18123
18341
|
function unionStrings(a, b) {
|
|
18124
18342
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
18125
18343
|
}
|
|
18126
18344
|
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
|
-
});
|
|
18345
|
+
const rows = await ctx.persistence.tombstones(embedding, embeddingModel, scope, opts.folderId);
|
|
18132
18346
|
let bestId = null;
|
|
18133
18347
|
let bestSim = opts.threshold;
|
|
18134
18348
|
for (const row of rows) {
|
|
@@ -18195,7 +18409,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18195
18409
|
if (requestedIds.length === 0) return null;
|
|
18196
18410
|
const valid = [];
|
|
18197
18411
|
for (const id of requestedIds) {
|
|
18198
|
-
const existing = await
|
|
18412
|
+
const existing = await ctx.persistence.get(id);
|
|
18199
18413
|
if (existing && !existing.supersededBy) valid.push(id);
|
|
18200
18414
|
}
|
|
18201
18415
|
if (valid.length === 0) {
|
|
@@ -18207,7 +18421,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18207
18421
|
return { supersede: valid, content: decision.content };
|
|
18208
18422
|
}
|
|
18209
18423
|
if (decision.action === "noop" && decision.targetId) {
|
|
18210
|
-
const existing = await
|
|
18424
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
18211
18425
|
if (!existing || existing.supersededBy) {
|
|
18212
18426
|
return abandonToRace(
|
|
18213
18427
|
options,
|
|
@@ -18221,8 +18435,9 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18221
18435
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
18222
18436
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
18223
18437
|
const resurrect = resurrectFields(existing);
|
|
18224
|
-
const updated = await
|
|
18438
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
18225
18439
|
content: existing.content,
|
|
18440
|
+
freeFormOnly: true,
|
|
18226
18441
|
proofCountIncrement: 1,
|
|
18227
18442
|
observationSourceIds: options.sourceChunkIds,
|
|
18228
18443
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -18249,7 +18464,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18249
18464
|
};
|
|
18250
18465
|
}
|
|
18251
18466
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
18252
|
-
const existing = await
|
|
18467
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
18253
18468
|
if (!existing || existing.supersededBy) {
|
|
18254
18469
|
return abandonToRace(
|
|
18255
18470
|
options,
|
|
@@ -18260,13 +18475,15 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18260
18475
|
existing.sourceChunkIds ?? [],
|
|
18261
18476
|
options.sourceChunkIds ?? []
|
|
18262
18477
|
);
|
|
18263
|
-
const
|
|
18478
|
+
const generatedEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
|
|
18479
|
+
const newEmbedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
18264
18480
|
const consolidatedModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18265
18481
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
18266
18482
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
18267
18483
|
const resurrect = resurrectFields(existing);
|
|
18268
|
-
const updated = await
|
|
18484
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
18269
18485
|
content: decision.content,
|
|
18486
|
+
freeFormOnly: true,
|
|
18270
18487
|
proofCountIncrement: 1,
|
|
18271
18488
|
observationSourceIds: options.sourceChunkIds,
|
|
18272
18489
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -18309,8 +18526,8 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18309
18526
|
return null;
|
|
18310
18527
|
}
|
|
18311
18528
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
18312
|
-
const stillExists = await
|
|
18313
|
-
if (stillExists) {
|
|
18529
|
+
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
18530
|
+
if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
|
|
18314
18531
|
throw new Error(`retain: merge into memory ${targetId} failed to persist`);
|
|
18315
18532
|
}
|
|
18316
18533
|
}
|
|
@@ -18824,9 +19041,9 @@ function createAutoExtractor(options) {
|
|
|
18824
19041
|
const persistCursor = (conversationId, messages, advancedToId, contiguous) => {
|
|
18825
19042
|
if (!cursorStore || conversationId === void 0 || !contiguous) return;
|
|
18826
19043
|
try {
|
|
18827
|
-
const
|
|
18828
|
-
if (
|
|
18829
|
-
const storedIdx = messages.findIndex((m) => m.id ===
|
|
19044
|
+
const stored2 = cursorStore.get(conversationId);
|
|
19045
|
+
if (stored2 && stored2 !== advancedToId) {
|
|
19046
|
+
const storedIdx = messages.findIndex((m) => m.id === stored2);
|
|
18830
19047
|
const newIdx = messages.findIndex((m) => m.id === advancedToId);
|
|
18831
19048
|
if (storedIdx !== -1 && newIdx !== -1 && storedIdx >= newIdx) return;
|
|
18832
19049
|
}
|
|
@@ -19795,7 +20012,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
19795
20012
|
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
19796
20013
|
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
19797
20014
|
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;
|
|
20015
|
+
const laneRan = types.includes("fact") && (!!ctx.factSource || !!ctx.vaultCtx && !!ctx.vaultCache) || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
|
|
19799
20016
|
const scores = admitted.map((m) => m.score);
|
|
19800
20017
|
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
19801
20018
|
const diagnostics = {
|
|
@@ -19837,7 +20054,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
19837
20054
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
19838
20055
|
}
|
|
19839
20056
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
19840
|
-
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
20057
|
+
const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
|
|
19841
20058
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
19842
20059
|
const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
|
|
19843
20060
|
const prepStart = nowMs2();
|
|
@@ -19867,7 +20084,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
19867
20084
|
safeLane(
|
|
19868
20085
|
"graph",
|
|
19869
20086
|
() => graphLaneFailed = true,
|
|
19870
|
-
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
20087
|
+
() => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
19871
20088
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
19872
20089
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
19873
20090
|
...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
|
|
@@ -19878,13 +20095,13 @@ async function recall(query, ctx, options = {}) {
|
|
|
19878
20095
|
wantsTemporal ? safeLane(
|
|
19879
20096
|
"temporal",
|
|
19880
20097
|
() => temporalLaneFailed = true,
|
|
19881
|
-
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
20098
|
+
() => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
19882
20099
|
) : Promise.resolve([])
|
|
19883
20100
|
]);
|
|
19884
20101
|
prepMs = nowMs2() - prepStart;
|
|
19885
20102
|
graphLaneCount = entityRanking.length;
|
|
19886
20103
|
temporalLaneCount = temporalRanking.length;
|
|
19887
|
-
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
20104
|
+
if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
|
|
19888
20105
|
const factStart = nowMs2();
|
|
19889
20106
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
19890
20107
|
factFloor = vaultMinScore;
|
|
@@ -19900,50 +20117,50 @@ async function recall(query, ctx, options = {}) {
|
|
|
19900
20117
|
rankedOnCosine: factRankedOnCosine,
|
|
19901
20118
|
decryptLast: factDecryptLast,
|
|
19902
20119
|
rowsDecrypted: factRowsDecrypted
|
|
19903
|
-
} = await searchVaultMemoriesWithSize(
|
|
19904
|
-
|
|
20120
|
+
} = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
|
|
20121
|
+
searchQuery,
|
|
19905
20122
|
ctx.vaultCtx,
|
|
19906
20123
|
ctx.embeddingOptions,
|
|
19907
20124
|
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
|
-
);
|
|
20125
|
+
searchOptions
|
|
20126
|
+
)))(query, {
|
|
20127
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
20128
|
+
minSimilarity: vaultMinScore,
|
|
20129
|
+
useFusion: true,
|
|
20130
|
+
rerank: flags.rerank,
|
|
20131
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
20132
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
20133
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
20134
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
20135
|
+
},
|
|
20136
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
20137
|
+
...options.recency && { recency: options.recency },
|
|
20138
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
20139
|
+
...options.supersessionBoost !== void 0 && {
|
|
20140
|
+
supersessionBoost: options.supersessionBoost
|
|
20141
|
+
},
|
|
20142
|
+
...options.supersessionWindow !== void 0 && {
|
|
20143
|
+
supersessionWindow: options.supersessionWindow
|
|
20144
|
+
},
|
|
20145
|
+
...options.proofCountAlpha !== void 0 && {
|
|
20146
|
+
proofCountAlpha: options.proofCountAlpha
|
|
20147
|
+
},
|
|
20148
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
20149
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
20150
|
+
},
|
|
20151
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
20152
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
20153
|
+
...subQueries && { subQueries },
|
|
20154
|
+
...options.scopes && { scopes: options.scopes },
|
|
20155
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
20156
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
20157
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
20158
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
20159
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
20160
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
20161
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
20162
|
+
queryEmbedTotalTimeoutMs
|
|
20163
|
+
});
|
|
19947
20164
|
factResults.push(
|
|
19948
20165
|
...dedupeBy(
|
|
19949
20166
|
results,
|
|
@@ -20748,26 +20965,26 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
20748
20965
|
};
|
|
20749
20966
|
const inputs = [];
|
|
20750
20967
|
for (const id of new Set(memoryIds)) {
|
|
20751
|
-
let
|
|
20968
|
+
let record2;
|
|
20752
20969
|
try {
|
|
20753
|
-
|
|
20970
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
20754
20971
|
} catch (err) {
|
|
20755
20972
|
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
20756
20973
|
skip(id, "not-found");
|
|
20757
20974
|
continue;
|
|
20758
20975
|
}
|
|
20759
|
-
if (
|
|
20976
|
+
if (record2.isDeleted || ctx.userId !== void 0 && record2.userId !== ctx.userId || record2.topicsUserManaged) {
|
|
20760
20977
|
skip(id, "excluded");
|
|
20761
20978
|
continue;
|
|
20762
20979
|
}
|
|
20763
20980
|
try {
|
|
20764
|
-
const
|
|
20765
|
-
|
|
20981
|
+
const stored2 = await vaultMemoryToStored(
|
|
20982
|
+
record2,
|
|
20766
20983
|
ctx.walletAddress,
|
|
20767
20984
|
ctx.signMessage,
|
|
20768
20985
|
ctx.embeddedWalletSigner
|
|
20769
20986
|
);
|
|
20770
|
-
inputs.push({ id, content:
|
|
20987
|
+
inputs.push({ id, content: stored2.content });
|
|
20771
20988
|
} catch (err) {
|
|
20772
20989
|
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
20773
20990
|
skip(id, "unreadable");
|
|
@@ -20952,6 +21169,780 @@ function createLocalMemoryStore(options) {
|
|
|
20952
21169
|
};
|
|
20953
21170
|
}
|
|
20954
21171
|
|
|
21172
|
+
// src/lib/memory/store/remotePersistence.ts
|
|
21173
|
+
var RemoteMemoryError = class extends Error {
|
|
21174
|
+
constructor(message, status, code) {
|
|
21175
|
+
super(message);
|
|
21176
|
+
this.status = status;
|
|
21177
|
+
this.code = code;
|
|
21178
|
+
this.name = "RemoteMemoryError";
|
|
21179
|
+
}
|
|
21180
|
+
};
|
|
21181
|
+
var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
|
|
21182
|
+
var memoryFields = {
|
|
21183
|
+
memory_id: true,
|
|
21184
|
+
content: true,
|
|
21185
|
+
scope: true,
|
|
21186
|
+
created_at: true,
|
|
21187
|
+
updated_at: true,
|
|
21188
|
+
is_deleted: true,
|
|
21189
|
+
embedding: true,
|
|
21190
|
+
embedding_model: true,
|
|
21191
|
+
kind: true,
|
|
21192
|
+
kind_value: true,
|
|
21193
|
+
level: true,
|
|
21194
|
+
folder_id: true,
|
|
21195
|
+
source_chunk_ids: true,
|
|
21196
|
+
proof_count: true,
|
|
21197
|
+
source: true,
|
|
21198
|
+
event_time_start: true,
|
|
21199
|
+
event_time_end: true,
|
|
21200
|
+
event_time_kind: true,
|
|
21201
|
+
topics_user_managed: true,
|
|
21202
|
+
topics: true,
|
|
21203
|
+
topics_updated_at: true,
|
|
21204
|
+
media: true,
|
|
21205
|
+
topics_extracted_at: true,
|
|
21206
|
+
topics_extracted_version: true,
|
|
21207
|
+
superseded_by: true,
|
|
21208
|
+
superseded_at: true,
|
|
21209
|
+
last_observed_at: true,
|
|
21210
|
+
fact_type: true,
|
|
21211
|
+
archived_at: true,
|
|
21212
|
+
trust_tier: true,
|
|
21213
|
+
visibility: true,
|
|
21214
|
+
twin_opt_in: true,
|
|
21215
|
+
published_at: true,
|
|
21216
|
+
geohash: true
|
|
21217
|
+
};
|
|
21218
|
+
var candidateListLimits = [
|
|
21219
|
+
["scopes", 20],
|
|
21220
|
+
["fact_types", 20],
|
|
21221
|
+
["memory_ids", 1e3],
|
|
21222
|
+
["force_ids", 100]
|
|
21223
|
+
];
|
|
21224
|
+
function record(value) {
|
|
21225
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21226
|
+
}
|
|
21227
|
+
function memoryRecord(value) {
|
|
21228
|
+
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))) {
|
|
21229
|
+
throw new Error("Invalid nearby private-memory response");
|
|
21230
|
+
}
|
|
21231
|
+
return value;
|
|
21232
|
+
}
|
|
21233
|
+
async function createRemoteMemoryPersistence(options) {
|
|
21234
|
+
const base = new URL(options.baseUrl);
|
|
21235
|
+
if (!/^https?:$/.test(base.protocol) || base.username || base.password || base.search || base.hash) {
|
|
21236
|
+
throw new Error(
|
|
21237
|
+
"baseUrl must be an HTTP(S) origin or base path without credentials, query or fragment"
|
|
21238
|
+
);
|
|
21239
|
+
}
|
|
21240
|
+
if (!options.keyId || options.keyId.length > 256)
|
|
21241
|
+
throw new Error("A canonical keyId is required");
|
|
21242
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
21243
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
21244
|
+
throw new Error("timeoutMs must be a positive number");
|
|
21245
|
+
const root = base.href.replace(/\/$/, "") + "/api/private-memories";
|
|
21246
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
21247
|
+
const request = async (path, init = {}, signal) => {
|
|
21248
|
+
const controller = new AbortController();
|
|
21249
|
+
let timedOut = false;
|
|
21250
|
+
const timer = setTimeout(() => {
|
|
21251
|
+
timedOut = true;
|
|
21252
|
+
controller.abort();
|
|
21253
|
+
}, timeoutMs);
|
|
21254
|
+
const forwardAbort = () => controller.abort(signal?.reason);
|
|
21255
|
+
if (signal?.aborted) forwardAbort();
|
|
21256
|
+
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
21257
|
+
let rejectAborted;
|
|
21258
|
+
const aborted = new Promise((_, reject) => {
|
|
21259
|
+
rejectAborted = () => reject(
|
|
21260
|
+
controller.signal.reason instanceof Error ? controller.signal.reason : new Error("Nearby request aborted")
|
|
21261
|
+
);
|
|
21262
|
+
if (controller.signal.aborted) rejectAborted();
|
|
21263
|
+
else controller.signal.addEventListener("abort", rejectAborted, { once: true });
|
|
21264
|
+
});
|
|
21265
|
+
aborted.catch(() => void 0);
|
|
21266
|
+
try {
|
|
21267
|
+
const token = await Promise.race([options.getToken(), aborted]);
|
|
21268
|
+
if (controller.signal.aborted) await aborted;
|
|
21269
|
+
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
21270
|
+
const response = await fetcher(root + path, {
|
|
21271
|
+
...init,
|
|
21272
|
+
headers: {
|
|
21273
|
+
Authorization: `Bearer ${token}`,
|
|
21274
|
+
...init.body ? { "Content-Type": "application/json" } : {}
|
|
21275
|
+
},
|
|
21276
|
+
redirect: "error",
|
|
21277
|
+
signal: controller.signal
|
|
21278
|
+
});
|
|
21279
|
+
if (!response.ok) {
|
|
21280
|
+
const body = await response.json().catch(() => null);
|
|
21281
|
+
throw new RemoteMemoryError(
|
|
21282
|
+
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
21283
|
+
response.status,
|
|
21284
|
+
record(body) && typeof body.code === "string" ? body.code : void 0
|
|
21285
|
+
);
|
|
21286
|
+
}
|
|
21287
|
+
return await response.json();
|
|
21288
|
+
} catch (error) {
|
|
21289
|
+
if (timedOut) throw new RemoteMemoryError("Nearby request timed out", 408, "timeout");
|
|
21290
|
+
throw error;
|
|
21291
|
+
} finally {
|
|
21292
|
+
clearTimeout(timer);
|
|
21293
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
21294
|
+
if (rejectAborted) controller.signal.removeEventListener("abort", rejectAborted);
|
|
21295
|
+
}
|
|
21296
|
+
};
|
|
21297
|
+
const account = await request("/account", {}, options.signal);
|
|
21298
|
+
if (!record(account) || account.state !== "active") {
|
|
21299
|
+
throw new RemoteMemoryError(
|
|
21300
|
+
"Complete and verify migration before using remote memories",
|
|
21301
|
+
409,
|
|
21302
|
+
"memory_not_active"
|
|
21303
|
+
);
|
|
21304
|
+
}
|
|
21305
|
+
if (account.key_id !== options.keyId) {
|
|
21306
|
+
throw new RemoteMemoryError(
|
|
21307
|
+
"The canonical memory key does not match this account",
|
|
21308
|
+
409,
|
|
21309
|
+
"key_mismatch"
|
|
21310
|
+
);
|
|
21311
|
+
}
|
|
21312
|
+
const snapshots = /* @__PURE__ */ new WeakMap();
|
|
21313
|
+
const decode = async (value) => {
|
|
21314
|
+
const item = memoryRecord(value);
|
|
21315
|
+
const decrypt = async (ciphertext) => {
|
|
21316
|
+
if (!ciphertextPattern.test(ciphertext))
|
|
21317
|
+
throw new Error("Nearby returned unencrypted memory content");
|
|
21318
|
+
const plaintext = await options.decrypt(ciphertext);
|
|
21319
|
+
if (plaintext === ciphertext) throw new Error("Memory decryption failed");
|
|
21320
|
+
return plaintext;
|
|
21321
|
+
};
|
|
21322
|
+
const decoded = {
|
|
21323
|
+
...item,
|
|
21324
|
+
memory: {
|
|
21325
|
+
...item.memory,
|
|
21326
|
+
content: await decrypt(item.memory.content),
|
|
21327
|
+
...item.memory.kind_value !== void 0 && {
|
|
21328
|
+
kind_value: await decrypt(item.memory.kind_value)
|
|
21329
|
+
}
|
|
21330
|
+
}
|
|
21331
|
+
};
|
|
21332
|
+
return remember(decoded, item);
|
|
21333
|
+
};
|
|
21334
|
+
const remember = (decoded, item) => {
|
|
21335
|
+
snapshots.set(decoded, {
|
|
21336
|
+
id: item.memory.memory_id,
|
|
21337
|
+
version: item.version,
|
|
21338
|
+
content: decoded.memory.content,
|
|
21339
|
+
kindValue: decoded.memory.kind_value,
|
|
21340
|
+
encryptedContent: item.memory.content,
|
|
21341
|
+
encryptedKindValue: item.memory.kind_value
|
|
21342
|
+
});
|
|
21343
|
+
return decoded;
|
|
21344
|
+
};
|
|
21345
|
+
const decodeAll = async (values) => {
|
|
21346
|
+
const records = values.map(memoryRecord);
|
|
21347
|
+
const settled = await Promise.allSettled(records.map(decode));
|
|
21348
|
+
const items = [];
|
|
21349
|
+
const failed = [];
|
|
21350
|
+
settled.forEach((result, i) => {
|
|
21351
|
+
if (result.status === "fulfilled") items.push(result.value);
|
|
21352
|
+
else
|
|
21353
|
+
failed.push({
|
|
21354
|
+
memory_id: records[i].memory.memory_id,
|
|
21355
|
+
version: records[i].version,
|
|
21356
|
+
error: result.reason instanceof Error ? result.reason : new Error(String(result.reason))
|
|
21357
|
+
});
|
|
21358
|
+
});
|
|
21359
|
+
return { items, failed };
|
|
21360
|
+
};
|
|
21361
|
+
const decodeCommitted = async (value, write) => {
|
|
21362
|
+
const item = memoryRecord(value);
|
|
21363
|
+
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)
|
|
21364
|
+
return decode(item);
|
|
21365
|
+
return remember(
|
|
21366
|
+
{
|
|
21367
|
+
...item,
|
|
21368
|
+
memory: {
|
|
21369
|
+
...item.memory,
|
|
21370
|
+
content: write.content,
|
|
21371
|
+
...write.kindValue !== void 0 && { kind_value: write.kindValue }
|
|
21372
|
+
}
|
|
21373
|
+
},
|
|
21374
|
+
item
|
|
21375
|
+
);
|
|
21376
|
+
};
|
|
21377
|
+
const encryptField2 = async (plaintext) => {
|
|
21378
|
+
const ciphertext = await options.encrypt(plaintext);
|
|
21379
|
+
if (ciphertext === plaintext || !ciphertextPattern.test(ciphertext))
|
|
21380
|
+
throw new Error("Field encryption must return SDK ciphertext; refusing to upload plaintext");
|
|
21381
|
+
return ciphertext;
|
|
21382
|
+
};
|
|
21383
|
+
const memoryPath = (id) => {
|
|
21384
|
+
if (!id || id.length > 128) throw new Error("memory_id must be 1\u2013128 characters");
|
|
21385
|
+
return "/memories/" + encodeURIComponent(id);
|
|
21386
|
+
};
|
|
21387
|
+
const prepareWrite = async (memory, expectedVersion, signal) => {
|
|
21388
|
+
const unknown = Object.keys(memory).filter(
|
|
21389
|
+
(key) => !Object.prototype.hasOwnProperty.call(memoryFields, key)
|
|
21390
|
+
);
|
|
21391
|
+
if (unknown.length) {
|
|
21392
|
+
throw new RemoteMemoryError(
|
|
21393
|
+
`Unknown private-memory fields (${unknown.join(", ")}); refusing to forward them`,
|
|
21394
|
+
400,
|
|
21395
|
+
"unknown_field"
|
|
21396
|
+
);
|
|
21397
|
+
}
|
|
21398
|
+
memory = { ...memory, ...memory.embedding && { embedding: [...memory.embedding] } };
|
|
21399
|
+
const path = memoryPath(memory.memory_id);
|
|
21400
|
+
const snapshot = typeof expectedVersion === "number" ? void 0 : snapshots.get(expectedVersion);
|
|
21401
|
+
if (typeof expectedVersion !== "number" && (!snapshot || snapshot.id !== memory.memory_id || snapshot.version !== expectedVersion.version))
|
|
21402
|
+
throw new Error(
|
|
21403
|
+
"Expected snapshot must be an unmodified version from this persistence instance"
|
|
21404
|
+
);
|
|
21405
|
+
expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
|
|
21406
|
+
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
21407
|
+
throw new Error("expectedVersion must be a nonnegative integer");
|
|
21408
|
+
const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
|
|
21409
|
+
let existing;
|
|
21410
|
+
if (expectedVersion !== 0 && !snapshot) {
|
|
21411
|
+
try {
|
|
21412
|
+
existing = memoryRecord(await request(path, {}, signal));
|
|
21413
|
+
} catch (error) {
|
|
21414
|
+
if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
|
|
21415
|
+
throw error;
|
|
21416
|
+
}
|
|
21417
|
+
}
|
|
21418
|
+
if (existing && existing.version !== expectedVersion) throw conflict();
|
|
21419
|
+
const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
|
|
21420
|
+
const content = (snapshot?.content ?? decoded?.memory.content) === memory.content ? snapshot?.encryptedContent ?? existing.memory.content : await encryptField2(memory.content);
|
|
21421
|
+
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);
|
|
21422
|
+
return {
|
|
21423
|
+
body: {
|
|
21424
|
+
expected_version: expectedVersion,
|
|
21425
|
+
memory: { ...memory, content, ...kindValue !== void 0 && { kind_value: kindValue } }
|
|
21426
|
+
},
|
|
21427
|
+
content: memory.content,
|
|
21428
|
+
kindValue: memory.kind_value
|
|
21429
|
+
};
|
|
21430
|
+
};
|
|
21431
|
+
const fetchCandidates = async (embedding, candidateOptions, withCounts) => {
|
|
21432
|
+
const limit = candidateOptions.limit ?? 100;
|
|
21433
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
21434
|
+
throw new Error("Candidate limit must be 1\u2013100");
|
|
21435
|
+
for (const [key, max] of candidateListLimits) {
|
|
21436
|
+
const values = candidateOptions[key];
|
|
21437
|
+
if (values && values.length > max)
|
|
21438
|
+
throw new Error(`Candidate ${key} accepts at most ${max} entries (got ${values.length})`);
|
|
21439
|
+
}
|
|
21440
|
+
const result = await request(
|
|
21441
|
+
"/candidates",
|
|
21442
|
+
{
|
|
21443
|
+
method: "POST",
|
|
21444
|
+
body: JSON.stringify({
|
|
21445
|
+
embedding,
|
|
21446
|
+
limit,
|
|
21447
|
+
force_ids: candidateOptions.force_ids ?? [],
|
|
21448
|
+
...withCounts && { with_counts: true },
|
|
21449
|
+
...Object.fromEntries(
|
|
21450
|
+
[
|
|
21451
|
+
"scopes",
|
|
21452
|
+
"memory_ids",
|
|
21453
|
+
"embedding_model",
|
|
21454
|
+
"strict_model",
|
|
21455
|
+
"include_deleted",
|
|
21456
|
+
"deleted_only"
|
|
21457
|
+
].filter(
|
|
21458
|
+
(key) => candidateOptions[key] !== void 0
|
|
21459
|
+
).map((key) => [key, candidateOptions[key]])
|
|
21460
|
+
),
|
|
21461
|
+
...candidateOptions.fact_types !== void 0 && {
|
|
21462
|
+
fact_types: candidateOptions.fact_types
|
|
21463
|
+
},
|
|
21464
|
+
...candidateOptions.include_archived !== void 0 && {
|
|
21465
|
+
include_archived: candidateOptions.include_archived
|
|
21466
|
+
},
|
|
21467
|
+
...candidateOptions.include_quarantined !== void 0 && {
|
|
21468
|
+
include_quarantined: candidateOptions.include_quarantined
|
|
21469
|
+
},
|
|
21470
|
+
...candidateOptions.include_superseded !== void 0 && {
|
|
21471
|
+
include_superseded: candidateOptions.include_superseded
|
|
21472
|
+
}
|
|
21473
|
+
})
|
|
21474
|
+
},
|
|
21475
|
+
candidateOptions.signal
|
|
21476
|
+
);
|
|
21477
|
+
if (!record(result) || !Array.isArray(result.items))
|
|
21478
|
+
throw new Error("Invalid nearby candidate response");
|
|
21479
|
+
return result;
|
|
21480
|
+
};
|
|
21481
|
+
const candidateSet = async (embedding, candidateOptions = {}) => {
|
|
21482
|
+
const result = await fetchCandidates(embedding, candidateOptions, true);
|
|
21483
|
+
if (!Number.isSafeInteger(result.total_count) || result.total_count < 0 || !Number.isSafeInteger(result.unavailable_count) || result.unavailable_count < 0)
|
|
21484
|
+
throw new Error("Invalid nearby candidate response");
|
|
21485
|
+
return {
|
|
21486
|
+
...await decodeAll(result.items),
|
|
21487
|
+
total_count: result.total_count,
|
|
21488
|
+
unavailable_count: result.unavailable_count
|
|
21489
|
+
};
|
|
21490
|
+
};
|
|
21491
|
+
return {
|
|
21492
|
+
get: async (id, signal) => {
|
|
21493
|
+
try {
|
|
21494
|
+
return await decode(await request(memoryPath(id), {}, signal));
|
|
21495
|
+
} catch (error) {
|
|
21496
|
+
if (error instanceof RemoteMemoryError && error.status === 404) return null;
|
|
21497
|
+
throw error;
|
|
21498
|
+
}
|
|
21499
|
+
},
|
|
21500
|
+
list: async (listOptions = {}) => {
|
|
21501
|
+
const { signal, ...query } = listOptions;
|
|
21502
|
+
if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200)) {
|
|
21503
|
+
throw new Error("Page limit must be 1\u2013200");
|
|
21504
|
+
}
|
|
21505
|
+
const params = new URLSearchParams();
|
|
21506
|
+
for (const key of [
|
|
21507
|
+
"cursor",
|
|
21508
|
+
"limit",
|
|
21509
|
+
"include_deleted",
|
|
21510
|
+
"include_archived",
|
|
21511
|
+
"include_quarantined",
|
|
21512
|
+
"include_superseded",
|
|
21513
|
+
"include_embeddings"
|
|
21514
|
+
]) {
|
|
21515
|
+
if (query[key] !== void 0) params.set(key, String(query[key]));
|
|
21516
|
+
}
|
|
21517
|
+
const page = await request("/memories?" + params.toString(), {}, signal);
|
|
21518
|
+
if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
|
|
21519
|
+
throw new Error("Invalid nearby private-memory page");
|
|
21520
|
+
}
|
|
21521
|
+
return {
|
|
21522
|
+
...await decodeAll(page.items),
|
|
21523
|
+
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
|
|
21524
|
+
};
|
|
21525
|
+
},
|
|
21526
|
+
put: async (memory, expectedVersion, signal) => {
|
|
21527
|
+
const write = await prepareWrite(memory, expectedVersion, signal);
|
|
21528
|
+
return decodeCommitted(
|
|
21529
|
+
await request(
|
|
21530
|
+
memoryPath(write.body.memory.memory_id),
|
|
21531
|
+
{
|
|
21532
|
+
method: "PUT",
|
|
21533
|
+
body: JSON.stringify({ key_id: options.keyId, ...write.body })
|
|
21534
|
+
},
|
|
21535
|
+
signal
|
|
21536
|
+
),
|
|
21537
|
+
write
|
|
21538
|
+
);
|
|
21539
|
+
},
|
|
21540
|
+
putMany: async (writes, signal) => {
|
|
21541
|
+
if (writes.length < 1 || writes.length > 50 || new Set(writes.map((w) => w.memory.memory_id)).size !== writes.length)
|
|
21542
|
+
throw new Error("Batch must contain 1\u201350 distinct memory ids");
|
|
21543
|
+
const prepared = await Promise.all(
|
|
21544
|
+
writes.map((w) => prepareWrite(w.memory, w.expectedVersion, signal))
|
|
21545
|
+
);
|
|
21546
|
+
const result = await request(
|
|
21547
|
+
"/memories/batch",
|
|
21548
|
+
{
|
|
21549
|
+
method: "POST",
|
|
21550
|
+
body: JSON.stringify({ key_id: options.keyId, writes: prepared.map((w) => w.body) })
|
|
21551
|
+
},
|
|
21552
|
+
signal
|
|
21553
|
+
);
|
|
21554
|
+
if (!record(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
|
|
21555
|
+
throw new Error("Invalid nearby batch response");
|
|
21556
|
+
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
21557
|
+
},
|
|
21558
|
+
candidateSet,
|
|
21559
|
+
candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
|
|
21560
|
+
};
|
|
21561
|
+
}
|
|
21562
|
+
|
|
21563
|
+
// src/lib/memory/store/remotePipeline.ts
|
|
21564
|
+
import { v7 as uuidv75 } from "uuid";
|
|
21565
|
+
function storedVector(vector) {
|
|
21566
|
+
if (!Array.isArray(vector) || vector.length !== 1536 && vector.length !== 4096 || vector.some((v) => !Number.isFinite(v)))
|
|
21567
|
+
throw new Error("Remote memories require a finite 1536/4096-dimensional vector");
|
|
21568
|
+
const out = vector.slice(0, 1536);
|
|
21569
|
+
const norm = Math.sqrt(out.reduce((sum, v) => sum + v * v, 0));
|
|
21570
|
+
if (!norm) throw new Error("Remote query/content vector has no direction after MRL truncation");
|
|
21571
|
+
return out.map((v) => v / norm);
|
|
21572
|
+
}
|
|
21573
|
+
function sourceIds(value) {
|
|
21574
|
+
if (!value) return [];
|
|
21575
|
+
try {
|
|
21576
|
+
const parsed = JSON.parse(value);
|
|
21577
|
+
return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string") : [];
|
|
21578
|
+
} catch {
|
|
21579
|
+
return [];
|
|
21580
|
+
}
|
|
21581
|
+
}
|
|
21582
|
+
function isMemoryLevel(value) {
|
|
21583
|
+
return MEMORY_LEVELS.includes(value);
|
|
21584
|
+
}
|
|
21585
|
+
function stored(row) {
|
|
21586
|
+
return {
|
|
21587
|
+
uniqueId: row.memory_id,
|
|
21588
|
+
content: row.content,
|
|
21589
|
+
scope: row.scope,
|
|
21590
|
+
folderId: row.folder_id ?? null,
|
|
21591
|
+
userId: null,
|
|
21592
|
+
kind: row.kind ?? null,
|
|
21593
|
+
kindValue: row.kind_value ?? null,
|
|
21594
|
+
...isMemoryLevel(row.level) && { level: row.level },
|
|
21595
|
+
embedding: row.embedding ? JSON.stringify(row.embedding) : null,
|
|
21596
|
+
embeddingModel: row.embedding_model ?? null,
|
|
21597
|
+
sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
|
|
21598
|
+
proofCount: row.proof_count ?? null,
|
|
21599
|
+
source: row.source ?? null,
|
|
21600
|
+
media: parseMedia(row.media),
|
|
21601
|
+
eventTimeStart: row.event_time_start ?? null,
|
|
21602
|
+
eventTimeEnd: row.event_time_end ?? null,
|
|
21603
|
+
eventTimeKind: row.event_time_kind ?? null,
|
|
21604
|
+
topicsUserManaged: row.topics_user_managed ?? false,
|
|
21605
|
+
topics: parseTopics(row.topics),
|
|
21606
|
+
topicsUpdatedAt: row.topics_updated_at ?? null,
|
|
21607
|
+
topicsExtractedAt: row.topics_extracted_at ?? null,
|
|
21608
|
+
topicsExtractedVersion: row.topics_extracted_version ?? null,
|
|
21609
|
+
supersededBy: row.superseded_by ?? null,
|
|
21610
|
+
supersededAt: row.superseded_at ?? null,
|
|
21611
|
+
lastObservedAt: row.last_observed_at ?? null,
|
|
21612
|
+
factType: row.fact_type ?? null,
|
|
21613
|
+
archivedAt: row.archived_at ?? null,
|
|
21614
|
+
trustTier: row.trust_tier ?? null,
|
|
21615
|
+
visibility: row.visibility === "public" ? "public" : "private",
|
|
21616
|
+
twinOptIn: row.twin_opt_in ?? false,
|
|
21617
|
+
publishedAt: row.published_at ?? null,
|
|
21618
|
+
geohash: row.geohash ?? null,
|
|
21619
|
+
createdAt: new Date(row.created_at),
|
|
21620
|
+
updatedAt: new Date(row.updated_at),
|
|
21621
|
+
isDeleted: row.is_deleted
|
|
21622
|
+
};
|
|
21623
|
+
}
|
|
21624
|
+
function createRemoteMemoryPipeline(options) {
|
|
21625
|
+
const { persistence, embeddingOptions } = options;
|
|
21626
|
+
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21627
|
+
const operation = (mode) => {
|
|
21628
|
+
const rejectUndecryptable = (failed) => {
|
|
21629
|
+
if (!failed.length) return;
|
|
21630
|
+
if (mode === "retain")
|
|
21631
|
+
throw new Error(
|
|
21632
|
+
`Remote memories could not decrypt ${failed.length} candidate row(s); refusing to retain until they are repaired`
|
|
21633
|
+
);
|
|
21634
|
+
getLogger().warn(
|
|
21635
|
+
`[memory/remote] Skipping ${failed.length} undecryptable candidate row(s)`,
|
|
21636
|
+
failed.map((failure) => failure.memory_id)
|
|
21637
|
+
);
|
|
21638
|
+
};
|
|
21639
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
21640
|
+
const remember = (items) => {
|
|
21641
|
+
items.forEach((item) => snapshots.set(item.memory.memory_id, item));
|
|
21642
|
+
return items.map((item) => stored(item.memory));
|
|
21643
|
+
};
|
|
21644
|
+
const get = async (id) => {
|
|
21645
|
+
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
21646
|
+
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
21647
|
+
snapshots.set(id, snapshot);
|
|
21648
|
+
return stored(snapshot.memory);
|
|
21649
|
+
};
|
|
21650
|
+
const prepare = async (query, search = {}) => {
|
|
21651
|
+
if (search.folderId !== void 0)
|
|
21652
|
+
throw new Error("Remote memories do not support folder filters");
|
|
21653
|
+
const facets = normalizeSubQueries(search.subQueries);
|
|
21654
|
+
const facetQueries = facets.length >= 2 ? facets : [];
|
|
21655
|
+
const start = Date.now();
|
|
21656
|
+
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
21657
|
+
const embed = (texts) => generateEmbeddings(texts, {
|
|
21658
|
+
...embeddingOptions,
|
|
21659
|
+
totalTimeoutMs: budgetMs
|
|
21660
|
+
});
|
|
21661
|
+
const embedFacets = async () => {
|
|
21662
|
+
if (!facetQueries.length) return [];
|
|
21663
|
+
try {
|
|
21664
|
+
const vectors2 = await embed(facetQueries);
|
|
21665
|
+
if (vectors2.length !== facetQueries.length)
|
|
21666
|
+
throw new Error("Incomplete facet embeddings");
|
|
21667
|
+
return vectors2.map(storedVector);
|
|
21668
|
+
} catch (error) {
|
|
21669
|
+
getLogger().warn(
|
|
21670
|
+
"[memory/remote] Facet embeddings unavailable; using primary query",
|
|
21671
|
+
error
|
|
21672
|
+
);
|
|
21673
|
+
return [];
|
|
21674
|
+
}
|
|
21675
|
+
};
|
|
21676
|
+
const [primary, facetEmbeddings] = await Promise.all([
|
|
21677
|
+
search.queryEmbedding ?? embed([query]).then((vectors2) => vectors2[0]),
|
|
21678
|
+
embedFacets()
|
|
21679
|
+
]);
|
|
21680
|
+
const queryEmbedding = storedVector(primary);
|
|
21681
|
+
const queryEmbedMs = Date.now() - start;
|
|
21682
|
+
const graph = search.entityRanking ?? [];
|
|
21683
|
+
const temporal = search.temporalRanking ?? [];
|
|
21684
|
+
const forced = /* @__PURE__ */ new Set();
|
|
21685
|
+
for (let i = 0; i < Math.max(graph.length, temporal.length) && forced.size < 100; i++) {
|
|
21686
|
+
if (graph[i] !== void 0) forced.add(graph[i]);
|
|
21687
|
+
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
21688
|
+
}
|
|
21689
|
+
const forceIds = [...forced];
|
|
21690
|
+
const windowOptions = (i, signal) => ({
|
|
21691
|
+
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
21692
|
+
force_ids: i === 0 ? forceIds : [],
|
|
21693
|
+
...search.scopes && { scopes: search.scopes },
|
|
21694
|
+
...search.factTypes && { fact_types: search.factTypes },
|
|
21695
|
+
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
21696
|
+
include_archived: search.includeArchived,
|
|
21697
|
+
embedding_model: model,
|
|
21698
|
+
...signal && { signal }
|
|
21699
|
+
});
|
|
21700
|
+
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
21701
|
+
let windows;
|
|
21702
|
+
if (mode === "retain") {
|
|
21703
|
+
windows = await Promise.all(
|
|
21704
|
+
vectors.map((embedding, i) => persistence.candidateSet(embedding, windowOptions(i)))
|
|
21705
|
+
);
|
|
21706
|
+
} else {
|
|
21707
|
+
const deadline = new AbortController();
|
|
21708
|
+
const timer = setTimeout(
|
|
21709
|
+
() => deadline.abort(
|
|
21710
|
+
new RemoteMemoryError("Remote recall exceeded its query budget", 408, "timeout")
|
|
21711
|
+
),
|
|
21712
|
+
Math.max(0, start + budgetMs - Date.now())
|
|
21713
|
+
);
|
|
21714
|
+
try {
|
|
21715
|
+
windows = await Promise.all(
|
|
21716
|
+
vectors.map(
|
|
21717
|
+
(embedding, i) => persistence.candidates(embedding, windowOptions(i, deadline.signal))
|
|
21718
|
+
)
|
|
21719
|
+
);
|
|
21720
|
+
} finally {
|
|
21721
|
+
clearTimeout(timer);
|
|
21722
|
+
}
|
|
21723
|
+
}
|
|
21724
|
+
rejectUndecryptable([
|
|
21725
|
+
...new Map(
|
|
21726
|
+
windows.flatMap((window2) => window2.failed).map((failure) => [failure.memory_id, failure])
|
|
21727
|
+
).values()
|
|
21728
|
+
]);
|
|
21729
|
+
const items = [
|
|
21730
|
+
...new Map(
|
|
21731
|
+
windows.flatMap((window2) => window2.items).map((item) => [item.memory.memory_id, item])
|
|
21732
|
+
).values()
|
|
21733
|
+
];
|
|
21734
|
+
const memories = remember(items);
|
|
21735
|
+
return {
|
|
21736
|
+
memories,
|
|
21737
|
+
embeddedItems: memories.map((memory) => ({
|
|
21738
|
+
id: memory.uniqueId,
|
|
21739
|
+
content: memory.content,
|
|
21740
|
+
embedding: JSON.parse(memory.embedding ?? "[]"),
|
|
21741
|
+
createdAt: memory.createdAt,
|
|
21742
|
+
updatedAt: memory.updatedAt,
|
|
21743
|
+
proofCount: memory.proofCount,
|
|
21744
|
+
lastObservedAt: memory.lastObservedAt,
|
|
21745
|
+
eventTimeStart: memory.eventTimeStart,
|
|
21746
|
+
eventTimeEnd: memory.eventTimeEnd,
|
|
21747
|
+
eventTimeKind: memory.eventTimeKind === "point" || memory.eventTimeKind === "range" || memory.eventTimeKind === "ongoing" ? memory.eventTimeKind : null,
|
|
21748
|
+
factType: memory.factType,
|
|
21749
|
+
sourceChunkIds: memory.sourceChunkIds
|
|
21750
|
+
})),
|
|
21751
|
+
queryEmbedding,
|
|
21752
|
+
facetEmbeddings,
|
|
21753
|
+
vaultSize: Math.max(windows[0].total_count ?? 0, items.length),
|
|
21754
|
+
embeddingFailure: windows.some((window2) => (window2.unavailable_count ?? 0) > 0),
|
|
21755
|
+
embeddingsUnavailable: (windows[0].total_count ?? items.length) > 0 && !memories.some((memory) => memory.embedding),
|
|
21756
|
+
decryptLast: true,
|
|
21757
|
+
rowsDecrypted: items.length,
|
|
21758
|
+
queryEmbedMs,
|
|
21759
|
+
rowsEmbedded: 0
|
|
21760
|
+
};
|
|
21761
|
+
};
|
|
21762
|
+
const createRow = (input) => {
|
|
21763
|
+
if (input.folderId !== void 0 && input.folderId !== null)
|
|
21764
|
+
throw new Error("Remote memories do not support folders");
|
|
21765
|
+
const now = Date.now();
|
|
21766
|
+
return {
|
|
21767
|
+
memory_id: uuidv75(),
|
|
21768
|
+
content: input.content,
|
|
21769
|
+
scope: input.scope ?? "private",
|
|
21770
|
+
created_at: now,
|
|
21771
|
+
updated_at: now,
|
|
21772
|
+
is_deleted: false,
|
|
21773
|
+
...input.embedding !== void 0 && {
|
|
21774
|
+
embedding: storedVector(JSON.parse(input.embedding)),
|
|
21775
|
+
embedding_model: input.embeddingModel
|
|
21776
|
+
},
|
|
21777
|
+
source_chunk_ids: JSON.stringify(input.sourceChunkIds ?? []),
|
|
21778
|
+
proof_count: input.proofCount ?? 1,
|
|
21779
|
+
source: input.source ?? "manual",
|
|
21780
|
+
...input.eventTime && {
|
|
21781
|
+
event_time_start: input.eventTime.start ?? void 0,
|
|
21782
|
+
event_time_end: input.eventTime.end ?? void 0,
|
|
21783
|
+
event_time_kind: input.eventTime.kind ?? void 0
|
|
21784
|
+
},
|
|
21785
|
+
fact_type: input.factType,
|
|
21786
|
+
trust_tier: normalizeTrustTier(input.trustTier) ?? void 0,
|
|
21787
|
+
geohash: input.geohash,
|
|
21788
|
+
visibility: "private",
|
|
21789
|
+
twin_opt_in: false
|
|
21790
|
+
};
|
|
21791
|
+
};
|
|
21792
|
+
const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
|
|
21793
|
+
const port = {
|
|
21794
|
+
prepare,
|
|
21795
|
+
get,
|
|
21796
|
+
getFresh: async (id) => {
|
|
21797
|
+
const current = await persistence.get(id);
|
|
21798
|
+
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
21799
|
+
},
|
|
21800
|
+
tombstones: async (embedding, embeddingModel, scope, folderId) => {
|
|
21801
|
+
if (folderId !== void 0) throw new Error("Remote memories do not support folders");
|
|
21802
|
+
const window2 = await persistence.candidateSet(storedVector(embedding), {
|
|
21803
|
+
limit: 1,
|
|
21804
|
+
scopes: [scope],
|
|
21805
|
+
embedding_model: embeddingModel,
|
|
21806
|
+
strict_model: true,
|
|
21807
|
+
include_deleted: true,
|
|
21808
|
+
deleted_only: true
|
|
21809
|
+
});
|
|
21810
|
+
rejectUndecryptable(window2.failed);
|
|
21811
|
+
return remember(window2.items);
|
|
21812
|
+
},
|
|
21813
|
+
create: (input) => write(createRow(input), 0),
|
|
21814
|
+
update: async (id, patch) => {
|
|
21815
|
+
const existing = await get(id);
|
|
21816
|
+
if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
|
|
21817
|
+
return null;
|
|
21818
|
+
const snapshot = snapshots.get(id);
|
|
21819
|
+
const memory = {
|
|
21820
|
+
...snapshot.memory,
|
|
21821
|
+
content: patch.content,
|
|
21822
|
+
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
|
|
21823
|
+
};
|
|
21824
|
+
if (patch.scope !== void 0) memory.scope = patch.scope;
|
|
21825
|
+
if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
|
|
21826
|
+
delete memory.embedding;
|
|
21827
|
+
delete memory.embedding_model;
|
|
21828
|
+
}
|
|
21829
|
+
if (patch.embedding !== void 0) {
|
|
21830
|
+
memory.embedding = patch.embedding === null ? [] : storedVector(JSON.parse(patch.embedding));
|
|
21831
|
+
memory.embedding_model = patch.embeddingModel ?? void 0;
|
|
21832
|
+
}
|
|
21833
|
+
const observed = sourceIds(memory.source_chunk_ids);
|
|
21834
|
+
const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
|
|
21835
|
+
if (patch.sourceChunkIds !== void 0)
|
|
21836
|
+
memory.source_chunk_ids = JSON.stringify(
|
|
21837
|
+
patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
|
|
21838
|
+
);
|
|
21839
|
+
if (!replay) {
|
|
21840
|
+
if (patch.proofCountIncrement !== void 0)
|
|
21841
|
+
memory.proof_count = (memory.proof_count ?? 1) + patch.proofCountIncrement;
|
|
21842
|
+
else if (patch.proofCount !== void 0) memory.proof_count = patch.proofCount;
|
|
21843
|
+
if (patch.lastObservedAt !== void 0) memory.last_observed_at = patch.lastObservedAt;
|
|
21844
|
+
}
|
|
21845
|
+
if (patch.source !== void 0) memory.source = patch.source;
|
|
21846
|
+
if (patch.factType !== void 0) memory.fact_type = patch.factType;
|
|
21847
|
+
if (patch.trustTier !== void 0)
|
|
21848
|
+
memory.trust_tier = normalizeTrustTier(patch.trustTier) ?? void 0;
|
|
21849
|
+
if (patch.topicsUserManaged !== void 0)
|
|
21850
|
+
memory.topics_user_managed = patch.topicsUserManaged;
|
|
21851
|
+
if (patch.eventTime !== void 0) {
|
|
21852
|
+
memory.event_time_start = patch.eventTime.start ?? void 0;
|
|
21853
|
+
memory.event_time_end = patch.eventTime.end ?? void 0;
|
|
21854
|
+
memory.event_time_kind = patch.eventTime.kind ?? void 0;
|
|
21855
|
+
}
|
|
21856
|
+
if (patch.restore) memory.archived_at = void 0;
|
|
21857
|
+
return write(memory, snapshot);
|
|
21858
|
+
},
|
|
21859
|
+
supersede: async (id, successor) => {
|
|
21860
|
+
const [target, newer] = await Promise.all([get(id), get(successor)]);
|
|
21861
|
+
if (!target || !newer || id === successor) return false;
|
|
21862
|
+
const old = snapshots.get(id);
|
|
21863
|
+
const next = snapshots.get(successor);
|
|
21864
|
+
remember(
|
|
21865
|
+
await persistence.putMany([
|
|
21866
|
+
{
|
|
21867
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
21868
|
+
expectedVersion: old
|
|
21869
|
+
},
|
|
21870
|
+
{ memory: next.memory, expectedVersion: next }
|
|
21871
|
+
])
|
|
21872
|
+
);
|
|
21873
|
+
return true;
|
|
21874
|
+
},
|
|
21875
|
+
createSuperseding: async (input, targetId) => {
|
|
21876
|
+
const target = await get(targetId);
|
|
21877
|
+
if (!target) return { created: null, retired: false };
|
|
21878
|
+
const snapshot = snapshots.get(targetId);
|
|
21879
|
+
const successor = createRow(input);
|
|
21880
|
+
const rows = remember(
|
|
21881
|
+
await persistence.putMany([
|
|
21882
|
+
{ memory: successor, expectedVersion: 0 },
|
|
21883
|
+
{
|
|
21884
|
+
memory: {
|
|
21885
|
+
...snapshot.memory,
|
|
21886
|
+
superseded_by: successor.memory_id,
|
|
21887
|
+
superseded_at: Date.now()
|
|
21888
|
+
},
|
|
21889
|
+
expectedVersion: snapshot
|
|
21890
|
+
}
|
|
21891
|
+
])
|
|
21892
|
+
);
|
|
21893
|
+
return { created: rows[0], retired: true };
|
|
21894
|
+
}
|
|
21895
|
+
};
|
|
21896
|
+
return { prepare, port };
|
|
21897
|
+
};
|
|
21898
|
+
return {
|
|
21899
|
+
recall: async (query, recallOptions = {}) => {
|
|
21900
|
+
const { prepare } = operation("recall");
|
|
21901
|
+
return recall(
|
|
21902
|
+
query,
|
|
21903
|
+
{
|
|
21904
|
+
embeddingOptions,
|
|
21905
|
+
factSource: {
|
|
21906
|
+
graphRanking: options.graphRanking,
|
|
21907
|
+
temporalRanking: options.temporalRanking,
|
|
21908
|
+
search: async (text12, searchOptions) => {
|
|
21909
|
+
const prepared = await prepare(text12, searchOptions);
|
|
21910
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
21911
|
+
text12,
|
|
21912
|
+
prepared,
|
|
21913
|
+
embeddingOptions,
|
|
21914
|
+
searchOptions
|
|
21915
|
+
);
|
|
21916
|
+
return {
|
|
21917
|
+
...ranked,
|
|
21918
|
+
rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
|
|
21919
|
+
decryptLast: true,
|
|
21920
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
21921
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
21922
|
+
rowsEmbedded: 0
|
|
21923
|
+
};
|
|
21924
|
+
}
|
|
21925
|
+
}
|
|
21926
|
+
},
|
|
21927
|
+
{ ...recallOptions, types: ["fact"] }
|
|
21928
|
+
);
|
|
21929
|
+
},
|
|
21930
|
+
retain: async (content, retainOptions) => {
|
|
21931
|
+
const { port } = operation("retain");
|
|
21932
|
+
return retainWithPersistence(
|
|
21933
|
+
content,
|
|
21934
|
+
{
|
|
21935
|
+
persistence: port,
|
|
21936
|
+
embeddingOptions,
|
|
21937
|
+
vaultCache: /* @__PURE__ */ new Map(),
|
|
21938
|
+
normalizeEmbedding: storedVector
|
|
21939
|
+
},
|
|
21940
|
+
retainOptions
|
|
21941
|
+
);
|
|
21942
|
+
}
|
|
21943
|
+
};
|
|
21944
|
+
}
|
|
21945
|
+
|
|
20955
21946
|
// src/lib/memory/synthesizeProfile.ts
|
|
20956
21947
|
var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
|
|
20957
21948
|
var DEFAULT_FACET_RECALL_LIMIT = 20;
|
|
@@ -27206,7 +28197,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
27206
28197
|
const recordName = `backup_${filename.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
27207
28198
|
const arrayBuffer = await content.arrayBuffer();
|
|
27208
28199
|
const base64Data = uint8ArrayToBase64(new Uint8Array(arrayBuffer));
|
|
27209
|
-
const
|
|
28200
|
+
const record2 = {
|
|
27210
28201
|
recordType: RECORD_TYPE,
|
|
27211
28202
|
recordName,
|
|
27212
28203
|
fields: {
|
|
@@ -27216,7 +28207,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
27216
28207
|
contentType: { value: content.type || "application/json" }
|
|
27217
28208
|
}
|
|
27218
28209
|
};
|
|
27219
|
-
const response = await database.saveRecords(
|
|
28210
|
+
const response = await database.saveRecords(record2);
|
|
27220
28211
|
if (!response.records || response.records.length === 0) {
|
|
27221
28212
|
throw new Error("Failed to upload file to iCloud");
|
|
27222
28213
|
}
|
|
@@ -27242,11 +28233,11 @@ async function listICloudFiles() {
|
|
|
27242
28233
|
while (response.continuationMarker) {
|
|
27243
28234
|
break;
|
|
27244
28235
|
}
|
|
27245
|
-
const files = allRecords.map((
|
|
27246
|
-
recordName:
|
|
27247
|
-
filename:
|
|
27248
|
-
modifiedAt: new Date(
|
|
27249
|
-
size: typeof
|
|
28236
|
+
const files = allRecords.map((record2) => ({
|
|
28237
|
+
recordName: record2.recordName,
|
|
28238
|
+
filename: record2.fields.filename?.value ?? "",
|
|
28239
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
28240
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
27250
28241
|
}));
|
|
27251
28242
|
return files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
27252
28243
|
}
|
|
@@ -27259,8 +28250,8 @@ async function downloadICloudFile(recordName) {
|
|
|
27259
28250
|
if (!response.records || response.records.length === 0) {
|
|
27260
28251
|
throw new Error(`File not found: ${recordName}`);
|
|
27261
28252
|
}
|
|
27262
|
-
const
|
|
27263
|
-
const dataField =
|
|
28253
|
+
const record2 = response.records[0];
|
|
28254
|
+
const dataField = record2.fields.data?.value;
|
|
27264
28255
|
if (!dataField) {
|
|
27265
28256
|
throw new Error("No data in record");
|
|
27266
28257
|
}
|
|
@@ -27294,12 +28285,12 @@ async function findICloudFile(filename) {
|
|
|
27294
28285
|
if (!response.records || response.records.length === 0) {
|
|
27295
28286
|
return null;
|
|
27296
28287
|
}
|
|
27297
|
-
const
|
|
28288
|
+
const record2 = response.records[0];
|
|
27298
28289
|
return {
|
|
27299
|
-
recordName:
|
|
27300
|
-
filename:
|
|
27301
|
-
modifiedAt: new Date(
|
|
27302
|
-
size: typeof
|
|
28290
|
+
recordName: record2.recordName,
|
|
28291
|
+
filename: record2.fields.filename?.value ?? "",
|
|
28292
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
28293
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
27303
28294
|
};
|
|
27304
28295
|
}
|
|
27305
28296
|
|
|
@@ -27457,8 +28448,8 @@ async function getStoredTokenData5(provider, walletAddress) {
|
|
|
27457
28448
|
return null;
|
|
27458
28449
|
}
|
|
27459
28450
|
}
|
|
27460
|
-
async function readTokenRow(
|
|
27461
|
-
if (
|
|
28451
|
+
async function readTokenRow(stored2, provider, walletAddress) {
|
|
28452
|
+
if (stored2.startsWith(ENCRYPTED_PREFIX6)) {
|
|
27462
28453
|
if (!walletAddress) {
|
|
27463
28454
|
getLogger().warn(
|
|
27464
28455
|
`Encrypted OAuth token found for ${provider} but no wallet address provided`
|
|
@@ -27466,7 +28457,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
27466
28457
|
return null;
|
|
27467
28458
|
}
|
|
27468
28459
|
try {
|
|
27469
|
-
const encryptedData =
|
|
28460
|
+
const encryptedData = stored2.slice(ENCRYPTED_PREFIX6.length);
|
|
27470
28461
|
let decryptedJson;
|
|
27471
28462
|
try {
|
|
27472
28463
|
decryptedJson = await decryptData(encryptedData, walletAddress);
|
|
@@ -27481,7 +28472,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
27481
28472
|
return null;
|
|
27482
28473
|
}
|
|
27483
28474
|
}
|
|
27484
|
-
return parsePlaintextToken(
|
|
28475
|
+
return parsePlaintextToken(stored2, walletAddress);
|
|
27485
28476
|
}
|
|
27486
28477
|
async function storeTokenData5(provider, data, walletAddress) {
|
|
27487
28478
|
if (typeof window === "undefined") return;
|
|
@@ -27557,8 +28548,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
27557
28548
|
const keys = [scopedKey, legacyKey];
|
|
27558
28549
|
const isEncrypted2 = (value) => !!value && value.startsWith(ENCRYPTED_PREFIX6);
|
|
27559
28550
|
const plaintextAt = (key) => {
|
|
27560
|
-
const
|
|
27561
|
-
return
|
|
28551
|
+
const stored2 = sessionStorage.getItem(key) ?? localStorage.getItem(key);
|
|
28552
|
+
return stored2 && !isEncrypted2(stored2) ? stored2 : null;
|
|
27562
28553
|
};
|
|
27563
28554
|
let tokenToMigrate = null;
|
|
27564
28555
|
for (const key of keys) {
|
|
@@ -27570,8 +28561,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
27570
28561
|
}
|
|
27571
28562
|
if (!tokenToMigrate) {
|
|
27572
28563
|
for (const key of keys) {
|
|
27573
|
-
const
|
|
27574
|
-
if (isEncrypted2(localStorage.getItem(key)) &&
|
|
28564
|
+
const stored2 = sessionStorage.getItem(key);
|
|
28565
|
+
if (isEncrypted2(localStorage.getItem(key)) && stored2 && !isEncrypted2(stored2)) {
|
|
27575
28566
|
sessionStorage.removeItem(key);
|
|
27576
28567
|
}
|
|
27577
28568
|
}
|
|
@@ -27627,17 +28618,17 @@ function storeOAuthState2(state) {
|
|
|
27627
28618
|
}
|
|
27628
28619
|
function getAndClearOAuthState4() {
|
|
27629
28620
|
if (typeof window === "undefined") return null;
|
|
27630
|
-
const
|
|
28621
|
+
const stored2 = sessionStorage.getItem(STATE_STORAGE_KEY);
|
|
27631
28622
|
sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
27632
|
-
if (!
|
|
28623
|
+
if (!stored2) return null;
|
|
27633
28624
|
try {
|
|
27634
|
-
const parsed = JSON.parse(
|
|
28625
|
+
const parsed = JSON.parse(stored2);
|
|
27635
28626
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
27636
28627
|
return parsed.state;
|
|
27637
28628
|
}
|
|
27638
28629
|
} catch {
|
|
27639
28630
|
}
|
|
27640
|
-
return
|
|
28631
|
+
return stored2;
|
|
27641
28632
|
}
|
|
27642
28633
|
function isDropboxCallback() {
|
|
27643
28634
|
if (typeof window === "undefined") return false;
|
|
@@ -27820,17 +28811,17 @@ function storeOAuthState3(state) {
|
|
|
27820
28811
|
}
|
|
27821
28812
|
function getAndClearOAuthState5() {
|
|
27822
28813
|
if (typeof window === "undefined") return null;
|
|
27823
|
-
const
|
|
28814
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY4);
|
|
27824
28815
|
sessionStorage.removeItem(CODE_STORAGE_KEY4);
|
|
27825
|
-
if (!
|
|
28816
|
+
if (!stored2) return null;
|
|
27826
28817
|
try {
|
|
27827
|
-
const parsed = JSON.parse(
|
|
28818
|
+
const parsed = JSON.parse(stored2);
|
|
27828
28819
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
27829
28820
|
return parsed.state;
|
|
27830
28821
|
}
|
|
27831
28822
|
} catch {
|
|
27832
28823
|
}
|
|
27833
|
-
return
|
|
28824
|
+
return stored2;
|
|
27834
28825
|
}
|
|
27835
28826
|
function isGoogleDriveCallback() {
|
|
27836
28827
|
if (typeof window === "undefined") return false;
|
|
@@ -29760,18 +30751,18 @@ async function blobToDataUri(blob) {
|
|
|
29760
30751
|
reader.readAsDataURL(blob);
|
|
29761
30752
|
});
|
|
29762
30753
|
}
|
|
29763
|
-
async function storedToLlmapiMessage(
|
|
29764
|
-
let textContent =
|
|
30754
|
+
async function storedToLlmapiMessage(stored2, encryptionKey, resolveMediaByIds) {
|
|
30755
|
+
let textContent = stored2.content;
|
|
29765
30756
|
const fileUrlMap = /* @__PURE__ */ new Map();
|
|
29766
30757
|
const imageParts = [];
|
|
29767
|
-
if (
|
|
29768
|
-
for (const file of
|
|
30758
|
+
if (stored2.role !== "assistant" && stored2.files?.length) {
|
|
30759
|
+
for (const file of stored2.files) {
|
|
29769
30760
|
if (isSendableImageURL(file.url)) {
|
|
29770
30761
|
imageParts.push({
|
|
29771
30762
|
type: "image_url",
|
|
29772
30763
|
image_url: { url: file.url }
|
|
29773
30764
|
});
|
|
29774
|
-
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl,
|
|
30765
|
+
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
29775
30766
|
imageParts.push({
|
|
29776
30767
|
type: "image_url",
|
|
29777
30768
|
image_url: { url: file.sourceUrl }
|
|
@@ -29791,11 +30782,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29791
30782
|
}
|
|
29792
30783
|
}
|
|
29793
30784
|
}
|
|
29794
|
-
} else if (
|
|
30785
|
+
} else if (stored2.role === "assistant" && stored2.files?.length) {
|
|
29795
30786
|
const expiredFileIds = [];
|
|
29796
|
-
for (const file of
|
|
30787
|
+
for (const file of stored2.files) {
|
|
29797
30788
|
if (file.sourceUrl) {
|
|
29798
|
-
if (!isR2UrlExpired(file.sourceUrl,
|
|
30789
|
+
if (!isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
29799
30790
|
fileUrlMap.set(file.id, file.sourceUrl);
|
|
29800
30791
|
} else {
|
|
29801
30792
|
expiredFileIds.push(file.id);
|
|
@@ -29808,11 +30799,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29808
30799
|
[${expiredFileIds.length} expired image URL${expiredFileIds.length > 1 ? "s" : ""} omitted \u2014 the user can still see ${expiredFileIds.length > 1 ? "them" : "it"} locally]`;
|
|
29809
30800
|
}
|
|
29810
30801
|
}
|
|
29811
|
-
if (
|
|
30802
|
+
if (stored2.fileIds?.length && resolveMediaByIds) {
|
|
29812
30803
|
try {
|
|
29813
|
-
const mediaItems = await resolveMediaByIds(
|
|
30804
|
+
const mediaItems = await resolveMediaByIds(stored2.fileIds);
|
|
29814
30805
|
for (const media of mediaItems) {
|
|
29815
|
-
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl,
|
|
30806
|
+
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl, stored2.createdAt)) {
|
|
29816
30807
|
fileUrlMap.set(media.mediaId, media.sourceUrl);
|
|
29817
30808
|
}
|
|
29818
30809
|
}
|
|
@@ -29836,7 +30827,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29836
30827
|
return "";
|
|
29837
30828
|
}
|
|
29838
30829
|
);
|
|
29839
|
-
if (
|
|
30830
|
+
if (stored2.role === "assistant" && fileUrlMap.size > 0) {
|
|
29840
30831
|
const unreferencedImages = [...fileUrlMap.entries()].filter(
|
|
29841
30832
|
([, url]) => !textContent.includes(url)
|
|
29842
30833
|
);
|
|
@@ -29848,11 +30839,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29848
30839
|
textContent = textContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
29849
30840
|
const content = [{ type: "text", text: textContent }, ...imageParts];
|
|
29850
30841
|
const messages = [];
|
|
29851
|
-
if (
|
|
30842
|
+
if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
|
|
29852
30843
|
messages.push({
|
|
29853
|
-
role:
|
|
30844
|
+
role: stored2.role,
|
|
29854
30845
|
content: void 0,
|
|
29855
|
-
tool_calls:
|
|
30846
|
+
tool_calls: stored2.toolCallEvents.map((event) => ({
|
|
29856
30847
|
id: event.id,
|
|
29857
30848
|
type: "function",
|
|
29858
30849
|
function: {
|
|
@@ -29861,7 +30852,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29861
30852
|
}
|
|
29862
30853
|
}))
|
|
29863
30854
|
});
|
|
29864
|
-
for (const event of
|
|
30855
|
+
for (const event of stored2.toolCallEvents) {
|
|
29865
30856
|
if (event.id && event.output !== void 0 && event.output !== null) {
|
|
29866
30857
|
messages.push({
|
|
29867
30858
|
role: "tool",
|
|
@@ -29872,12 +30863,12 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
29872
30863
|
}
|
|
29873
30864
|
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
30865
|
messages.push({
|
|
29875
|
-
role:
|
|
30866
|
+
role: stored2.role,
|
|
29876
30867
|
content: [{ type: "text", text: postToolText }]
|
|
29877
30868
|
});
|
|
29878
30869
|
} else {
|
|
29879
30870
|
messages.push({
|
|
29880
|
-
role:
|
|
30871
|
+
role: stored2.role,
|
|
29881
30872
|
content
|
|
29882
30873
|
});
|
|
29883
30874
|
}
|
|
@@ -33708,19 +34699,19 @@ function startObserve(entry, walletAddress) {
|
|
|
33708
34699
|
"updated_at"
|
|
33709
34700
|
]).subscribe({
|
|
33710
34701
|
next: (records) => {
|
|
33711
|
-
const
|
|
33712
|
-
if (!
|
|
34702
|
+
const record2 = records[0];
|
|
34703
|
+
if (!record2) return;
|
|
33713
34704
|
const patch = {
|
|
33714
34705
|
userPreference: {
|
|
33715
|
-
uniqueId:
|
|
33716
|
-
walletAddress:
|
|
33717
|
-
nickname:
|
|
33718
|
-
occupation:
|
|
33719
|
-
description:
|
|
33720
|
-
models:
|
|
33721
|
-
personality:
|
|
33722
|
-
createdAt:
|
|
33723
|
-
updatedAt:
|
|
34706
|
+
uniqueId: record2.id,
|
|
34707
|
+
walletAddress: record2.walletAddress,
|
|
34708
|
+
nickname: record2.nickname,
|
|
34709
|
+
occupation: record2.occupation,
|
|
34710
|
+
description: record2.description,
|
|
34711
|
+
models: record2.models,
|
|
34712
|
+
personality: record2.personality,
|
|
34713
|
+
createdAt: record2.createdAt,
|
|
34714
|
+
updatedAt: record2.updatedAt
|
|
33724
34715
|
}
|
|
33725
34716
|
};
|
|
33726
34717
|
if (isInitialEmission) {
|
|
@@ -34930,7 +35921,10 @@ export {
|
|
|
34930
35921
|
LoggerProvider,
|
|
34931
35922
|
MAX_HOPS,
|
|
34932
35923
|
MEDIUM_TTL_MS,
|
|
35924
|
+
MEMORY_KINDS,
|
|
35925
|
+
MEMORY_LEVELS,
|
|
34933
35926
|
MemoryEntity as MemoryEntityModel,
|
|
35927
|
+
MemoryLevelError,
|
|
34934
35928
|
NEVER_TTL_MS,
|
|
34935
35929
|
NODE_BUDGET,
|
|
34936
35930
|
PAST_EVENT_GRACE_MS,
|
|
@@ -34943,6 +35937,7 @@ export {
|
|
|
34943
35937
|
R2_DEFAULT_TTL_MS,
|
|
34944
35938
|
RECALL_MAX_LIMIT,
|
|
34945
35939
|
RECALL_TOOL_NAME,
|
|
35940
|
+
RemoteMemoryError,
|
|
34946
35941
|
RerankerUnavailableError,
|
|
34947
35942
|
SDK_SCHEMA_VERSION,
|
|
34948
35943
|
SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -35034,6 +36029,8 @@ export {
|
|
|
35034
36029
|
createPlatformCursorStore,
|
|
35035
36030
|
createProjectOp,
|
|
35036
36031
|
createRecallTool,
|
|
36032
|
+
createRemoteMemoryPersistence,
|
|
36033
|
+
createRemoteMemoryPipeline,
|
|
35037
36034
|
createSavedToolOp,
|
|
35038
36035
|
createServerToolsFilter,
|
|
35039
36036
|
createStockPricePreProcessor,
|