@anuma/sdk 6.33.2 → 6.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +1099 -293
- package/dist/expo/index.d.mts +218 -4
- package/dist/expo/index.d.ts +218 -4
- package/dist/expo/index.mjs +1095 -293
- package/dist/index.cjs +18 -6
- package/dist/index.mjs +18 -6
- package/dist/react/index.cjs +1180 -374
- package/dist/react/index.d.mts +251 -4
- package/dist/react/index.d.ts +251 -4
- package/dist/react/index.mjs +1176 -374
- package/dist/server/index.cjs +118 -86
- package/dist/server/index.d.mts +77 -3
- package/dist/server/index.d.ts +77 -3
- package/dist/server/index.mjs +118 -86
- package/dist/telemetry/index.d.mts +3 -4
- package/dist/telemetry/index.d.ts +3 -4
- package/dist/tools/selection/index.cjs +18 -6
- package/dist/tools/selection/index.mjs +18 -6
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -1437,6 +1437,7 @@ __export(index_exports, {
|
|
|
1437
1437
|
R2_DEFAULT_TTL_MS: () => R2_DEFAULT_TTL_MS,
|
|
1438
1438
|
RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
|
|
1439
1439
|
RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
|
|
1440
|
+
RemoteMemoryError: () => RemoteMemoryError,
|
|
1440
1441
|
RerankerUnavailableError: () => RerankerUnavailableError,
|
|
1441
1442
|
SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
|
|
1442
1443
|
SERVER_TOOL_DEPENDENCY_SETS: () => SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -1528,6 +1529,8 @@ __export(index_exports, {
|
|
|
1528
1529
|
createPlatformCursorStore: () => createPlatformCursorStore,
|
|
1529
1530
|
createProjectOp: () => createProjectOp,
|
|
1530
1531
|
createRecallTool: () => createRecallTool,
|
|
1532
|
+
createRemoteMemoryPersistence: () => createRemoteMemoryPersistence,
|
|
1533
|
+
createRemoteMemoryPipeline: () => createRemoteMemoryPipeline,
|
|
1531
1534
|
createSavedToolOp: () => createSavedToolOp,
|
|
1532
1535
|
createServerToolsFilter: () => createServerToolsFilter,
|
|
1533
1536
|
createStockPricePreProcessor: () => createStockPricePreProcessor,
|
|
@@ -3554,10 +3557,10 @@ function parsePlaintextToken(raw, walletAddress) {
|
|
|
3554
3557
|
return null;
|
|
3555
3558
|
}
|
|
3556
3559
|
if (!parsed || typeof parsed !== "object") return null;
|
|
3557
|
-
const
|
|
3558
|
-
const data =
|
|
3560
|
+
const record2 = parsed;
|
|
3561
|
+
const data = record2.token?.accessToken ? record2.token : record2;
|
|
3559
3562
|
if (!data?.accessToken) return null;
|
|
3560
|
-
if (
|
|
3563
|
+
if (record2.wallet && record2.wallet !== walletAddress) return null;
|
|
3561
3564
|
return data;
|
|
3562
3565
|
}
|
|
3563
3566
|
function promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress) {
|
|
@@ -3681,8 +3684,8 @@ async function storeTokenData(data, walletAddress) {
|
|
|
3681
3684
|
getLogger().warn("Failed to encrypt GitHub OAuth token:", error);
|
|
3682
3685
|
}
|
|
3683
3686
|
}
|
|
3684
|
-
const
|
|
3685
|
-
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(
|
|
3687
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
3688
|
+
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(record2));
|
|
3686
3689
|
}
|
|
3687
3690
|
function clearGithubToken(walletAddress) {
|
|
3688
3691
|
if (typeof window === "undefined") return;
|
|
@@ -3731,17 +3734,17 @@ function storeOAuthState(state) {
|
|
|
3731
3734
|
}
|
|
3732
3735
|
function getAndClearOAuthState() {
|
|
3733
3736
|
if (typeof window === "undefined") return null;
|
|
3734
|
-
const
|
|
3737
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY);
|
|
3735
3738
|
sessionStorage.removeItem(CODE_STORAGE_KEY);
|
|
3736
|
-
if (!
|
|
3739
|
+
if (!stored2) return null;
|
|
3737
3740
|
try {
|
|
3738
|
-
const parsed = JSON.parse(
|
|
3741
|
+
const parsed = JSON.parse(stored2);
|
|
3739
3742
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
3740
3743
|
return parsed.state;
|
|
3741
3744
|
}
|
|
3742
3745
|
} catch {
|
|
3743
3746
|
}
|
|
3744
|
-
return
|
|
3747
|
+
return stored2;
|
|
3745
3748
|
}
|
|
3746
3749
|
function isGithubCallback(callbackPath) {
|
|
3747
3750
|
if (typeof window === "undefined") return false;
|
|
@@ -4034,8 +4037,8 @@ async function storeTokenData2(data, walletAddress) {
|
|
|
4034
4037
|
getLogger().warn("Failed to encrypt Calendar OAuth token:", error);
|
|
4035
4038
|
}
|
|
4036
4039
|
}
|
|
4037
|
-
const
|
|
4038
|
-
sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(
|
|
4040
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
4041
|
+
sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(record2));
|
|
4039
4042
|
}
|
|
4040
4043
|
function clearCalendarToken(walletAddress) {
|
|
4041
4044
|
if (typeof window === "undefined") return;
|
|
@@ -4075,17 +4078,17 @@ function getRedirectUri2(callbackPath) {
|
|
|
4075
4078
|
}
|
|
4076
4079
|
function getAndClearOAuthState2() {
|
|
4077
4080
|
if (typeof window === "undefined") return null;
|
|
4078
|
-
const
|
|
4081
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY2);
|
|
4079
4082
|
sessionStorage.removeItem(CODE_STORAGE_KEY2);
|
|
4080
|
-
if (!
|
|
4083
|
+
if (!stored2) return null;
|
|
4081
4084
|
try {
|
|
4082
|
-
const parsed = JSON.parse(
|
|
4085
|
+
const parsed = JSON.parse(stored2);
|
|
4083
4086
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
4084
4087
|
return parsed.state;
|
|
4085
4088
|
}
|
|
4086
4089
|
} catch {
|
|
4087
4090
|
}
|
|
4088
|
-
return
|
|
4091
|
+
return stored2;
|
|
4089
4092
|
}
|
|
4090
4093
|
function isCalendarCallback(callbackPath) {
|
|
4091
4094
|
if (typeof window === "undefined") return false;
|
|
@@ -4360,8 +4363,8 @@ async function storeTokenData3(data, walletAddress) {
|
|
|
4360
4363
|
getLogger().warn("Failed to encrypt Drive OAuth token:", error);
|
|
4361
4364
|
}
|
|
4362
4365
|
}
|
|
4363
|
-
const
|
|
4364
|
-
sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(
|
|
4366
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
4367
|
+
sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(record2));
|
|
4365
4368
|
}
|
|
4366
4369
|
function clearDriveToken(walletAddress) {
|
|
4367
4370
|
if (typeof window === "undefined") return;
|
|
@@ -4401,17 +4404,17 @@ function getRedirectUri3(callbackPath) {
|
|
|
4401
4404
|
}
|
|
4402
4405
|
function getAndClearOAuthState3() {
|
|
4403
4406
|
if (typeof window === "undefined") return null;
|
|
4404
|
-
const
|
|
4407
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY3);
|
|
4405
4408
|
sessionStorage.removeItem(CODE_STORAGE_KEY3);
|
|
4406
|
-
if (!
|
|
4409
|
+
if (!stored2) return null;
|
|
4407
4410
|
try {
|
|
4408
|
-
const parsed = JSON.parse(
|
|
4411
|
+
const parsed = JSON.parse(stored2);
|
|
4409
4412
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
4410
4413
|
return parsed.state;
|
|
4411
4414
|
}
|
|
4412
4415
|
} catch {
|
|
4413
4416
|
}
|
|
4414
|
-
return
|
|
4417
|
+
return stored2;
|
|
4415
4418
|
}
|
|
4416
4419
|
function isDriveCallback(callbackPath) {
|
|
4417
4420
|
if (typeof window === "undefined") return false;
|
|
@@ -4741,11 +4744,11 @@ function storePKCEState(pkce) {
|
|
|
4741
4744
|
}
|
|
4742
4745
|
function getAndClearPKCEState() {
|
|
4743
4746
|
if (typeof window === "undefined") return null;
|
|
4744
|
-
const
|
|
4747
|
+
const stored2 = sessionStorage.getItem(PKCE_STORAGE_KEY);
|
|
4745
4748
|
sessionStorage.removeItem(PKCE_STORAGE_KEY);
|
|
4746
|
-
if (!
|
|
4749
|
+
if (!stored2) return null;
|
|
4747
4750
|
try {
|
|
4748
|
-
return JSON.parse(
|
|
4751
|
+
return JSON.parse(stored2);
|
|
4749
4752
|
} catch {
|
|
4750
4753
|
return null;
|
|
4751
4754
|
}
|
|
@@ -4763,8 +4766,8 @@ async function storeTokenData4(data, walletAddress) {
|
|
|
4763
4766
|
} catch {
|
|
4764
4767
|
}
|
|
4765
4768
|
}
|
|
4766
|
-
const
|
|
4767
|
-
sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(
|
|
4769
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
4770
|
+
sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(record2));
|
|
4768
4771
|
}
|
|
4769
4772
|
async function getStoredTokenData4(walletAddress) {
|
|
4770
4773
|
if (typeof window === "undefined") return null;
|
|
@@ -4780,12 +4783,12 @@ async function getStoredTokenData4(walletAddress) {
|
|
|
4780
4783
|
cachedWalletAddress4 = null;
|
|
4781
4784
|
}
|
|
4782
4785
|
try {
|
|
4783
|
-
const
|
|
4784
|
-
if (
|
|
4786
|
+
const stored2 = localStorage.getItem(getTokenStorageKey4(walletAddress));
|
|
4787
|
+
if (stored2?.startsWith(ENCRYPTED_PREFIX5)) {
|
|
4785
4788
|
if (walletAddress && hasEncryptionKey(walletAddress)) {
|
|
4786
4789
|
try {
|
|
4787
4790
|
const cryptoKey = await getEncryptionKey(walletAddress);
|
|
4788
|
-
const encrypted =
|
|
4791
|
+
const encrypted = stored2.slice(ENCRYPTED_PREFIX5.length);
|
|
4789
4792
|
const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
|
|
4790
4793
|
const data = JSON.parse(decrypted);
|
|
4791
4794
|
if (data.accessToken) return data;
|
|
@@ -4894,12 +4897,12 @@ async function getClientRegistration(walletAddress) {
|
|
|
4894
4897
|
if (typeof window === "undefined") return null;
|
|
4895
4898
|
try {
|
|
4896
4899
|
const scopedKey = getClientRegistrationStorageKey(walletAddress);
|
|
4897
|
-
const
|
|
4898
|
-
if (
|
|
4900
|
+
const stored2 = localStorage.getItem(scopedKey);
|
|
4901
|
+
if (stored2?.startsWith(ENCRYPTED_PREFIX5)) {
|
|
4899
4902
|
if (walletAddress && hasEncryptionKey(walletAddress)) {
|
|
4900
4903
|
try {
|
|
4901
4904
|
const cryptoKey = await getEncryptionKey(walletAddress);
|
|
4902
|
-
const encrypted =
|
|
4905
|
+
const encrypted = stored2.slice(ENCRYPTED_PREFIX5.length);
|
|
4903
4906
|
const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
|
|
4904
4907
|
const data = JSON.parse(decrypted);
|
|
4905
4908
|
if (data.clientId) {
|
|
@@ -4909,8 +4912,8 @@ async function getClientRegistration(walletAddress) {
|
|
|
4909
4912
|
}
|
|
4910
4913
|
}
|
|
4911
4914
|
}
|
|
4912
|
-
if (
|
|
4913
|
-
const data = JSON.parse(
|
|
4915
|
+
if (stored2 && !stored2.startsWith(ENCRYPTED_PREFIX5)) {
|
|
4916
|
+
const data = JSON.parse(stored2);
|
|
4914
4917
|
if (!data.clientId) return null;
|
|
4915
4918
|
return data;
|
|
4916
4919
|
}
|
|
@@ -6755,13 +6758,13 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
6755
6758
|
const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
6756
6759
|
return Promise.all(
|
|
6757
6760
|
topK.map(async ({ message, similarity }) => {
|
|
6758
|
-
const
|
|
6761
|
+
const stored2 = await messageRawToStored(
|
|
6759
6762
|
message,
|
|
6760
6763
|
ctx.walletAddress,
|
|
6761
6764
|
ctx.signMessage,
|
|
6762
6765
|
ctx.embeddedWalletSigner
|
|
6763
6766
|
);
|
|
6764
|
-
return { ...
|
|
6767
|
+
return { ...stored2, similarity };
|
|
6765
6768
|
})
|
|
6766
6769
|
);
|
|
6767
6770
|
}
|
|
@@ -6865,13 +6868,13 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
6865
6868
|
const storedById = new Map(
|
|
6866
6869
|
await Promise.all(
|
|
6867
6870
|
Array.from(uniqueMessages, async ([id, m]) => {
|
|
6868
|
-
const
|
|
6871
|
+
const stored2 = await messageRawToStored(
|
|
6869
6872
|
m,
|
|
6870
6873
|
ctx.walletAddress,
|
|
6871
6874
|
ctx.signMessage,
|
|
6872
6875
|
ctx.embeddedWalletSigner
|
|
6873
6876
|
);
|
|
6874
|
-
return [id,
|
|
6877
|
+
return [id, stored2];
|
|
6875
6878
|
})
|
|
6876
6879
|
)
|
|
6877
6880
|
);
|
|
@@ -6889,18 +6892,18 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
6889
6892
|
})
|
|
6890
6893
|
);
|
|
6891
6894
|
return topK.map(({ message, similarity, chunkTextSource }) => {
|
|
6892
|
-
const
|
|
6895
|
+
const stored2 = { ...storedById.get(message.id) };
|
|
6893
6896
|
let chunkText2;
|
|
6894
6897
|
if (chunkTextSource.kind === "chunk") {
|
|
6895
|
-
chunkText2 = resolveChunkText(
|
|
6898
|
+
chunkText2 = resolveChunkText(stored2.content, chunkTextSource.chunk, chunkTextSource.siblings);
|
|
6896
6899
|
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
6897
6900
|
const state = chunkStateByMsgId.get(message.id);
|
|
6898
6901
|
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
6899
|
-
chunkText2 = resolveChunkText(
|
|
6902
|
+
chunkText2 = resolveChunkText(stored2.content, chunk, state?.chunks);
|
|
6900
6903
|
} else {
|
|
6901
|
-
chunkText2 =
|
|
6904
|
+
chunkText2 = stored2.content;
|
|
6902
6905
|
}
|
|
6903
|
-
return { chunkText: chunkText2, message:
|
|
6906
|
+
return { chunkText: chunkText2, message: stored2, similarity };
|
|
6904
6907
|
});
|
|
6905
6908
|
}
|
|
6906
6909
|
async function getAllFilesOp(ctx, options) {
|
|
@@ -7250,7 +7253,7 @@ async function embedOne(text12, options, outer) {
|
|
|
7250
7253
|
}
|
|
7251
7254
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
7252
7255
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
7253
|
-
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
|
|
7256
|
+
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs, outer) {
|
|
7254
7257
|
const response = await withEmbeddingRetry(
|
|
7255
7258
|
() => withDeadline(
|
|
7256
7259
|
(signal) => postApiV1Embeddings({
|
|
@@ -7260,8 +7263,10 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
7260
7263
|
...signal && { signal }
|
|
7261
7264
|
}),
|
|
7262
7265
|
timeoutMs,
|
|
7263
|
-
"embedding batch request"
|
|
7264
|
-
|
|
7266
|
+
"embedding batch request",
|
|
7267
|
+
outer
|
|
7268
|
+
),
|
|
7269
|
+
outer
|
|
7265
7270
|
);
|
|
7266
7271
|
if (response.error) {
|
|
7267
7272
|
throw embeddingErrorFrom(response);
|
|
@@ -7279,6 +7284,11 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
7279
7284
|
}
|
|
7280
7285
|
async function generateEmbeddings(texts, options) {
|
|
7281
7286
|
if (texts.length === 0) return [];
|
|
7287
|
+
const total = options.totalTimeoutMs;
|
|
7288
|
+
if (total === void 0) return embedMany(texts, options, void 0);
|
|
7289
|
+
return withDeadline((signal) => embedMany(texts, options, signal), total, "embedding batch");
|
|
7290
|
+
}
|
|
7291
|
+
async function embedMany(texts, options, outer) {
|
|
7282
7292
|
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
7283
7293
|
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
7284
7294
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
@@ -7299,7 +7309,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
7299
7309
|
if (uncachedTexts.length === 0) {
|
|
7300
7310
|
return results;
|
|
7301
7311
|
}
|
|
7302
|
-
const headers = await resolveAuthHeaders(options);
|
|
7312
|
+
const headers = await resolveAuthHeaders(options, outer);
|
|
7313
|
+
if (outer?.aborted) throw outer.reason;
|
|
7303
7314
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
7304
7315
|
let newEmbeddings;
|
|
7305
7316
|
if (uncachedTexts.length <= chunkSize) {
|
|
@@ -7310,7 +7321,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
7310
7321
|
embeddingModel,
|
|
7311
7322
|
options.onUsage,
|
|
7312
7323
|
options.maskInput,
|
|
7313
|
-
timeoutMs
|
|
7324
|
+
timeoutMs,
|
|
7325
|
+
outer
|
|
7314
7326
|
);
|
|
7315
7327
|
} else {
|
|
7316
7328
|
const chunks = [];
|
|
@@ -7321,6 +7333,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
7321
7333
|
let nextIndex = 0;
|
|
7322
7334
|
const worker = async () => {
|
|
7323
7335
|
while (nextIndex < chunks.length) {
|
|
7336
|
+
if (outer?.aborted) throw outer.reason;
|
|
7324
7337
|
const idx = nextIndex++;
|
|
7325
7338
|
allEmbeddings[idx] = await generateEmbeddingsBatch(
|
|
7326
7339
|
chunks[idx],
|
|
@@ -7329,7 +7342,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
7329
7342
|
embeddingModel,
|
|
7330
7343
|
options.onUsage,
|
|
7331
7344
|
options.maskInput,
|
|
7332
|
-
timeoutMs
|
|
7345
|
+
timeoutMs,
|
|
7346
|
+
outer
|
|
7333
7347
|
);
|
|
7334
7348
|
}
|
|
7335
7349
|
};
|
|
@@ -7340,6 +7354,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
7340
7354
|
await Promise.all(workers);
|
|
7341
7355
|
newEmbeddings = allEmbeddings.flat();
|
|
7342
7356
|
}
|
|
7357
|
+
if (outer?.aborted) throw outer.reason;
|
|
7343
7358
|
for (let i = 0; i < uncachedIndices.length; i++) {
|
|
7344
7359
|
const f32Embedding = Float32Array.from(newEmbeddings[i]);
|
|
7345
7360
|
results[uncachedIndices[i]] = Array.from(f32Embedding);
|
|
@@ -12513,15 +12528,15 @@ function createSummaryContext(database) {
|
|
|
12513
12528
|
summariesCollection: database.get("conversation_summaries")
|
|
12514
12529
|
};
|
|
12515
12530
|
}
|
|
12516
|
-
function modelToStored(
|
|
12531
|
+
function modelToStored(record2) {
|
|
12517
12532
|
return {
|
|
12518
|
-
uniqueId:
|
|
12519
|
-
conversationId:
|
|
12520
|
-
summary:
|
|
12521
|
-
summarizedUpTo:
|
|
12522
|
-
tokenCount:
|
|
12523
|
-
createdAt:
|
|
12524
|
-
updatedAt:
|
|
12533
|
+
uniqueId: record2.id,
|
|
12534
|
+
conversationId: record2.conversationId,
|
|
12535
|
+
summary: record2.summary,
|
|
12536
|
+
summarizedUpTo: record2.summarizedUpTo,
|
|
12537
|
+
tokenCount: record2.tokenCount,
|
|
12538
|
+
createdAt: record2.createdAt,
|
|
12539
|
+
updatedAt: record2.updatedAt
|
|
12525
12540
|
};
|
|
12526
12541
|
}
|
|
12527
12542
|
async function getConversationSummaryOp(ctx, conversationId) {
|
|
@@ -12530,17 +12545,17 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
12530
12545
|
return modelToStored(results[0]);
|
|
12531
12546
|
}
|
|
12532
12547
|
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
12533
|
-
let
|
|
12548
|
+
let record2;
|
|
12534
12549
|
await ctx.database.write(async () => {
|
|
12535
12550
|
const existing = await ctx.summariesCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId)).fetch();
|
|
12536
12551
|
if (existing.length > 0) {
|
|
12537
|
-
|
|
12552
|
+
record2 = await existing[0].update((rec) => {
|
|
12538
12553
|
rec.summary = summary;
|
|
12539
12554
|
rec.summarizedUpTo = summarizedUpTo;
|
|
12540
12555
|
rec.tokenCount = tokenCount;
|
|
12541
12556
|
});
|
|
12542
12557
|
} else {
|
|
12543
|
-
|
|
12558
|
+
record2 = await ctx.summariesCollection.create((rec) => {
|
|
12544
12559
|
rec.conversationId = conversationId;
|
|
12545
12560
|
rec.summary = summary;
|
|
12546
12561
|
rec.summarizedUpTo = summarizedUpTo;
|
|
@@ -12548,13 +12563,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
|
|
|
12548
12563
|
});
|
|
12549
12564
|
}
|
|
12550
12565
|
});
|
|
12551
|
-
return modelToStored(
|
|
12566
|
+
return modelToStored(record2);
|
|
12552
12567
|
}
|
|
12553
12568
|
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
12554
12569
|
await ctx.database.write(async () => {
|
|
12555
12570
|
const existing = await ctx.summariesCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId)).fetch();
|
|
12556
|
-
for (const
|
|
12557
|
-
await
|
|
12571
|
+
for (const record2 of existing) {
|
|
12572
|
+
await record2.destroyPermanently();
|
|
12558
12573
|
}
|
|
12559
12574
|
});
|
|
12560
12575
|
}
|
|
@@ -12747,25 +12762,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
12747
12762
|
const kindBackfills = existing.filter((e) => {
|
|
12748
12763
|
const incoming = kindByName.get(e.canonicalName);
|
|
12749
12764
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
12750
|
-
}).map((
|
|
12765
|
+
}).map((record2) => ({ record: record2, kind: kindByName.get(record2.canonicalName) }));
|
|
12751
12766
|
const missing = unique.filter((n) => !existingNames.has(n));
|
|
12752
12767
|
const created = missing.map(
|
|
12753
|
-
(name) => ctx.entityCollection.prepareCreate((
|
|
12754
|
-
|
|
12768
|
+
(name) => ctx.entityCollection.prepareCreate((record2) => {
|
|
12769
|
+
record2._setRaw("canonical_name", name);
|
|
12755
12770
|
const kind = kindByName.get(name);
|
|
12756
|
-
if (kind !== void 0)
|
|
12771
|
+
if (kind !== void 0) record2._setRaw("kind", kind);
|
|
12757
12772
|
})
|
|
12758
12773
|
);
|
|
12759
12774
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
12760
|
-
for (const
|
|
12761
|
-
for (const { record, kind } of kindBackfills) {
|
|
12762
|
-
out.set(
|
|
12775
|
+
for (const record2 of created) out.set(record2.canonicalName, entityToStored(record2));
|
|
12776
|
+
for (const { record: record2, kind } of kindBackfills) {
|
|
12777
|
+
out.set(record2.canonicalName, { ...entityToStored(record2), kind });
|
|
12763
12778
|
}
|
|
12764
12779
|
return { entities: out, operations: created, kindBackfills };
|
|
12765
12780
|
}
|
|
12766
12781
|
function prepareKindBackfills(backfills) {
|
|
12767
12782
|
return backfills.map(
|
|
12768
|
-
({ record, kind }) =>
|
|
12783
|
+
({ record: record2, kind }) => record2.prepareUpdate((r) => {
|
|
12769
12784
|
r._setRaw("kind", kind);
|
|
12770
12785
|
})
|
|
12771
12786
|
);
|
|
@@ -12796,10 +12811,10 @@ function displayNamesOf(entities) {
|
|
|
12796
12811
|
}
|
|
12797
12812
|
return out;
|
|
12798
12813
|
}
|
|
12799
|
-
function topicsEqual(
|
|
12800
|
-
if (
|
|
12814
|
+
function topicsEqual(stored2, computed) {
|
|
12815
|
+
if (stored2 === null || stored2.length !== computed.length) return false;
|
|
12801
12816
|
const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
|
|
12802
|
-
const storedKeys =
|
|
12817
|
+
const storedKeys = stored2.map(key).sort();
|
|
12803
12818
|
const computedKeys = computed.map(key).sort();
|
|
12804
12819
|
return storedKeys.every((k, i) => k === computedKeys[i]);
|
|
12805
12820
|
}
|
|
@@ -12865,10 +12880,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
12865
12880
|
return;
|
|
12866
12881
|
}
|
|
12867
12882
|
const linkOps = toCreate.map(
|
|
12868
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
if (userId !== void 0)
|
|
12883
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
|
|
12884
|
+
record2._setRaw("memory_id", memoryId);
|
|
12885
|
+
record2._setRaw("entity_id", e.uniqueId);
|
|
12886
|
+
if (userId !== void 0) record2._setRaw("user_id", userId);
|
|
12872
12887
|
})
|
|
12873
12888
|
);
|
|
12874
12889
|
await ctx.database.batch(
|
|
@@ -12936,10 +12951,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
12936
12951
|
...entityOps,
|
|
12937
12952
|
...prepareKindBackfills(kindBackfills),
|
|
12938
12953
|
...toCreate.map(
|
|
12939
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
if (userId !== void 0)
|
|
12954
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
|
|
12955
|
+
record2._setRaw("memory_id", memoryId);
|
|
12956
|
+
record2._setRaw("entity_id", e.uniqueId);
|
|
12957
|
+
if (userId !== void 0) record2._setRaw("user_id", userId);
|
|
12943
12958
|
})
|
|
12944
12959
|
),
|
|
12945
12960
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
@@ -15009,13 +15024,13 @@ async function relinkMisclassifiedVideosOp(ctx, walletAddress) {
|
|
|
15009
15024
|
toRelink.push({ media, ext: mime.split("/")[1] || "mp4" });
|
|
15010
15025
|
continue;
|
|
15011
15026
|
}
|
|
15012
|
-
const
|
|
15027
|
+
const stored2 = await mediaToStored(
|
|
15013
15028
|
media,
|
|
15014
15029
|
ctx.walletAddress,
|
|
15015
15030
|
ctx.signMessage,
|
|
15016
15031
|
ctx.embeddedWalletSigner
|
|
15017
15032
|
);
|
|
15018
|
-
const ext = videoExtensionOf(
|
|
15033
|
+
const ext = videoExtensionOf(stored2.sourceUrl) ?? videoExtensionOf(stored2.name);
|
|
15019
15034
|
if (ext) {
|
|
15020
15035
|
toRelink.push({ media, ext });
|
|
15021
15036
|
}
|
|
@@ -15313,8 +15328,8 @@ function visibilityConditions(requested) {
|
|
|
15313
15328
|
if (excluded.length === 0) return [];
|
|
15314
15329
|
return [import_watermelondb23.Q.or(import_watermelondb23.Q.where("visibility", null), import_watermelondb23.Q.where("visibility", import_watermelondb23.Q.notIn(excluded)))];
|
|
15315
15330
|
}
|
|
15316
|
-
function isOwnedByCtxUser(ctx,
|
|
15317
|
-
return ctx.userId === void 0 ||
|
|
15331
|
+
function isOwnedByCtxUser(ctx, record2) {
|
|
15332
|
+
return ctx.userId === void 0 || record2.userId === ctx.userId;
|
|
15318
15333
|
}
|
|
15319
15334
|
function baseVaultConditions(ctx, options) {
|
|
15320
15335
|
return [
|
|
@@ -15394,39 +15409,39 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
15394
15409
|
}
|
|
15395
15410
|
return raw;
|
|
15396
15411
|
}
|
|
15397
|
-
function populateNewVaultMemory(
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
-
|
|
15402
|
-
|
|
15412
|
+
function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
|
|
15413
|
+
record2._setRaw("content", encryptedContent);
|
|
15414
|
+
record2._setRaw("scope", opts.scope ?? "private");
|
|
15415
|
+
record2._setRaw("folder_id", opts.folderId ?? null);
|
|
15416
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
15417
|
+
record2._setRaw("is_deleted", false);
|
|
15403
15418
|
if (opts.embedding !== void 0) {
|
|
15404
|
-
|
|
15405
|
-
|
|
15419
|
+
record2._setRaw("embedding", opts.embedding);
|
|
15420
|
+
record2._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
15406
15421
|
}
|
|
15407
15422
|
if (opts.sourceChunkIds !== void 0) {
|
|
15408
|
-
|
|
15423
|
+
record2._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
|
|
15409
15424
|
}
|
|
15410
|
-
|
|
15411
|
-
|
|
15425
|
+
record2._setRaw("proof_count", opts.proofCount ?? 1);
|
|
15426
|
+
record2._setRaw("source", opts.source ?? "manual");
|
|
15412
15427
|
if (opts.eventTime) {
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15428
|
+
record2._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
15429
|
+
record2._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
15430
|
+
record2._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
15416
15431
|
}
|
|
15417
15432
|
if (opts.factType !== void 0) {
|
|
15418
|
-
|
|
15433
|
+
record2._setRaw("fact_type", opts.factType);
|
|
15419
15434
|
}
|
|
15420
15435
|
if (opts.trustTier !== void 0) {
|
|
15421
|
-
|
|
15436
|
+
record2._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
15422
15437
|
}
|
|
15423
|
-
|
|
15424
|
-
|
|
15438
|
+
record2._setRaw("visibility", opts.visibility ?? "private");
|
|
15439
|
+
record2._setRaw(
|
|
15425
15440
|
"published_at",
|
|
15426
15441
|
opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
|
|
15427
15442
|
);
|
|
15428
15443
|
if (opts.geohash !== void 0) {
|
|
15429
|
-
|
|
15444
|
+
record2._setRaw("geohash", opts.geohash);
|
|
15430
15445
|
}
|
|
15431
15446
|
}
|
|
15432
15447
|
async function createVaultMemoryOp(ctx, opts) {
|
|
@@ -15440,7 +15455,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
15440
15455
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
15441
15456
|
throw new Error("Memory source is no longer eligible");
|
|
15442
15457
|
return ctx.vaultMemoryCollection.create(
|
|
15443
|
-
(
|
|
15458
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
15444
15459
|
);
|
|
15445
15460
|
});
|
|
15446
15461
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -15465,7 +15480,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
15465
15480
|
}
|
|
15466
15481
|
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
|
|
15467
15482
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
15468
|
-
(
|
|
15483
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
15469
15484
|
);
|
|
15470
15485
|
await target.update((r) => {
|
|
15471
15486
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -15547,7 +15562,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
15547
15562
|
throw new Error("Memory source is no longer eligible");
|
|
15548
15563
|
const prepared = optionsArray.map(
|
|
15549
15564
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
15550
|
-
(
|
|
15565
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
|
|
15551
15566
|
)
|
|
15552
15567
|
);
|
|
15553
15568
|
await ctx.database.batch(...prepared);
|
|
@@ -15555,16 +15570,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
15555
15570
|
});
|
|
15556
15571
|
return Promise.all(
|
|
15557
15572
|
created.map(
|
|
15558
|
-
(
|
|
15573
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
15559
15574
|
)
|
|
15560
15575
|
);
|
|
15561
15576
|
}
|
|
15562
15577
|
async function getVaultMemoryOp(ctx, id) {
|
|
15563
15578
|
try {
|
|
15564
|
-
const
|
|
15565
|
-
if (
|
|
15579
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
15580
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15566
15581
|
return vaultMemoryToStored(
|
|
15567
|
-
|
|
15582
|
+
record2,
|
|
15568
15583
|
ctx.walletAddress,
|
|
15569
15584
|
ctx.signMessage,
|
|
15570
15585
|
ctx.embeddedWalletSigner
|
|
@@ -15622,11 +15637,11 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
15622
15637
|
};
|
|
15623
15638
|
}
|
|
15624
15639
|
async function vaultMemoryRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner) {
|
|
15625
|
-
const
|
|
15640
|
+
const stored2 = vaultMemoryRawToStoredRaw(raw);
|
|
15626
15641
|
if (walletAddress) {
|
|
15627
|
-
return decryptVaultMemoryFields(
|
|
15642
|
+
return decryptVaultMemoryFields(stored2, walletAddress, signMessage, embeddedWalletSigner);
|
|
15628
15643
|
}
|
|
15629
|
-
return
|
|
15644
|
+
return stored2;
|
|
15630
15645
|
}
|
|
15631
15646
|
async function getAllVaultMemoriesOp(ctx, options) {
|
|
15632
15647
|
const conditions = [
|
|
@@ -15778,13 +15793,13 @@ async function getVaultMemoriesByIdsOp(ctx, ids, options) {
|
|
|
15778
15793
|
async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
15779
15794
|
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
|
|
15780
15795
|
return mapInBatches(results, async (raw) => {
|
|
15781
|
-
const
|
|
15796
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
15782
15797
|
raw,
|
|
15783
15798
|
ctx.walletAddress,
|
|
15784
15799
|
ctx.signMessage,
|
|
15785
15800
|
ctx.embeddedWalletSigner
|
|
15786
15801
|
);
|
|
15787
|
-
return
|
|
15802
|
+
return stored2.content;
|
|
15788
15803
|
});
|
|
15789
15804
|
}
|
|
15790
15805
|
async function countActiveVaultMemoriesOp(ctx) {
|
|
@@ -15806,12 +15821,12 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15806
15821
|
ctx.embeddedWalletSigner
|
|
15807
15822
|
) : opts.content;
|
|
15808
15823
|
let stale = false;
|
|
15809
|
-
const
|
|
15810
|
-
const originalUpdatedAt =
|
|
15824
|
+
const record2 = probe;
|
|
15825
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15811
15826
|
await ctx.database.write(async () => {
|
|
15812
15827
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
15813
15828
|
throw new Error("Memory source is no longer eligible");
|
|
15814
|
-
if (
|
|
15829
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
15815
15830
|
stale = true;
|
|
15816
15831
|
return;
|
|
15817
15832
|
}
|
|
@@ -15819,14 +15834,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15819
15834
|
let replayedObservation = false;
|
|
15820
15835
|
if (opts.observationSourceIds?.length) {
|
|
15821
15836
|
try {
|
|
15822
|
-
const parsed = JSON.parse(
|
|
15837
|
+
const parsed = JSON.parse(record2.sourceChunkIds ?? "[]");
|
|
15823
15838
|
if (Array.isArray(parsed))
|
|
15824
15839
|
observedSources = parsed.filter((id2) => typeof id2 === "string");
|
|
15825
15840
|
} catch {
|
|
15826
15841
|
}
|
|
15827
15842
|
replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
|
|
15828
15843
|
}
|
|
15829
|
-
await
|
|
15844
|
+
await record2.update((r) => {
|
|
15830
15845
|
r._setRaw("content", encryptedContent);
|
|
15831
15846
|
if (opts.scope !== void 0) {
|
|
15832
15847
|
r._setRaw("scope", opts.scope);
|
|
@@ -15883,7 +15898,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15883
15898
|
});
|
|
15884
15899
|
if (stale) return null;
|
|
15885
15900
|
return vaultMemoryToStored(
|
|
15886
|
-
|
|
15901
|
+
record2,
|
|
15887
15902
|
ctx.walletAddress,
|
|
15888
15903
|
ctx.signMessage,
|
|
15889
15904
|
ctx.embeddedWalletSigner
|
|
@@ -15897,21 +15912,21 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
15897
15912
|
if (!entityCtx) {
|
|
15898
15913
|
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
15899
15914
|
}
|
|
15900
|
-
let
|
|
15915
|
+
let record2;
|
|
15901
15916
|
try {
|
|
15902
|
-
|
|
15917
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
15903
15918
|
} catch {
|
|
15904
15919
|
return null;
|
|
15905
15920
|
}
|
|
15906
|
-
if (
|
|
15921
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15907
15922
|
let stale = false;
|
|
15908
|
-
const originalUpdatedAt =
|
|
15923
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15909
15924
|
await ctx.database.write(async (writer) => {
|
|
15910
|
-
if (
|
|
15925
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15911
15926
|
stale = true;
|
|
15912
15927
|
return;
|
|
15913
15928
|
}
|
|
15914
|
-
await
|
|
15929
|
+
await record2.update((r) => {
|
|
15915
15930
|
r._setRaw("topics_user_managed", true);
|
|
15916
15931
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
15917
15932
|
});
|
|
@@ -15935,25 +15950,25 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
15935
15950
|
);
|
|
15936
15951
|
});
|
|
15937
15952
|
if (stale) return null;
|
|
15938
|
-
return vaultMemoryToStored(
|
|
15953
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
15939
15954
|
}
|
|
15940
15955
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
15941
|
-
let
|
|
15956
|
+
let record2;
|
|
15942
15957
|
try {
|
|
15943
|
-
|
|
15958
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
15944
15959
|
} catch {
|
|
15945
15960
|
return false;
|
|
15946
15961
|
}
|
|
15947
|
-
if (
|
|
15948
|
-
const originalUpdatedAt =
|
|
15962
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
15963
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15949
15964
|
let cleared = false;
|
|
15950
15965
|
await ctx.database.write(async () => {
|
|
15951
|
-
if (options?.unlessTopicsRecorded && parseTopics(
|
|
15966
|
+
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
15952
15967
|
cleared = true;
|
|
15953
|
-
await
|
|
15968
|
+
await record2.update((r) => {
|
|
15954
15969
|
r._setRaw("topics_user_managed", false);
|
|
15955
15970
|
r._setRaw("topics_extracted_version", null);
|
|
15956
|
-
if (
|
|
15971
|
+
if (record2.topicsExtractedAt === null) {
|
|
15957
15972
|
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
15958
15973
|
}
|
|
15959
15974
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -15962,22 +15977,22 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
15962
15977
|
return cleared;
|
|
15963
15978
|
}
|
|
15964
15979
|
async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
15965
|
-
let
|
|
15980
|
+
let record2;
|
|
15966
15981
|
try {
|
|
15967
|
-
|
|
15982
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
15968
15983
|
} catch {
|
|
15969
15984
|
return null;
|
|
15970
15985
|
}
|
|
15971
|
-
if (
|
|
15986
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15972
15987
|
let stale = false;
|
|
15973
15988
|
await ctx.database.write(async () => {
|
|
15974
|
-
if (
|
|
15989
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15975
15990
|
stale = true;
|
|
15976
15991
|
return;
|
|
15977
15992
|
}
|
|
15978
|
-
const currentUpdatedAt =
|
|
15979
|
-
const currentPublishedAt =
|
|
15980
|
-
await
|
|
15993
|
+
const currentUpdatedAt = record2.updatedAt.getTime();
|
|
15994
|
+
const currentPublishedAt = record2.publishedAt ?? null;
|
|
15995
|
+
await record2.update((r) => {
|
|
15981
15996
|
r._setRaw("visibility", opts.visibility);
|
|
15982
15997
|
if (opts.visibility === "private") {
|
|
15983
15998
|
r._setRaw("published_at", null);
|
|
@@ -15991,19 +16006,19 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
15991
16006
|
});
|
|
15992
16007
|
});
|
|
15993
16008
|
if (stale) return null;
|
|
15994
|
-
return vaultMemoryToStored(
|
|
16009
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
15995
16010
|
}
|
|
15996
16011
|
async function deleteVaultMemoryOp(ctx, id) {
|
|
15997
16012
|
try {
|
|
15998
|
-
const
|
|
15999
|
-
if (
|
|
16013
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16014
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16000
16015
|
let stale = false;
|
|
16001
16016
|
await ctx.database.write(async () => {
|
|
16002
|
-
if (
|
|
16017
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
16003
16018
|
stale = true;
|
|
16004
16019
|
return;
|
|
16005
16020
|
}
|
|
16006
|
-
await
|
|
16021
|
+
await record2.update((r) => {
|
|
16007
16022
|
r._setRaw("is_deleted", true);
|
|
16008
16023
|
});
|
|
16009
16024
|
});
|
|
@@ -16022,8 +16037,8 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
16022
16037
|
async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
16023
16038
|
if (id === supersededById) return false;
|
|
16024
16039
|
try {
|
|
16025
|
-
const
|
|
16026
|
-
if (
|
|
16040
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16041
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16027
16042
|
let successor;
|
|
16028
16043
|
try {
|
|
16029
16044
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -16037,7 +16052,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
16037
16052
|
await ctx.database.write(async () => {
|
|
16038
16053
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
16039
16054
|
throw new Error("Memory source is no longer eligible");
|
|
16040
|
-
if (
|
|
16055
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
16041
16056
|
stale = true;
|
|
16042
16057
|
return;
|
|
16043
16058
|
}
|
|
@@ -16045,7 +16060,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
16045
16060
|
stale = true;
|
|
16046
16061
|
return;
|
|
16047
16062
|
}
|
|
16048
|
-
await
|
|
16063
|
+
await record2.update((r) => {
|
|
16049
16064
|
r._setRaw("superseded_by", supersededById);
|
|
16050
16065
|
r._setRaw("superseded_at", Date.now());
|
|
16051
16066
|
});
|
|
@@ -16064,7 +16079,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
16064
16079
|
const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
|
|
16065
16080
|
return mapInBatches(
|
|
16066
16081
|
results,
|
|
16067
|
-
(
|
|
16082
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
16068
16083
|
);
|
|
16069
16084
|
}
|
|
16070
16085
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
@@ -16206,17 +16221,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
16206
16221
|
}
|
|
16207
16222
|
}
|
|
16208
16223
|
const eligible = records.filter(
|
|
16209
|
-
(
|
|
16224
|
+
(record2) => !record2.isDeleted && isOwnedByCtxUser(ctx, record2) && !record2.topicsUserManaged
|
|
16210
16225
|
);
|
|
16211
|
-
const prepared = eligible.map((
|
|
16212
|
-
const originalUpdatedAt =
|
|
16213
|
-
return
|
|
16226
|
+
const prepared = eligible.map((record2) => {
|
|
16227
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
16228
|
+
return record2.prepareUpdate((r) => {
|
|
16214
16229
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
16215
16230
|
r._setRaw("topics_extracted_version", version);
|
|
16216
16231
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
16217
16232
|
});
|
|
16218
16233
|
});
|
|
16219
|
-
for (const
|
|
16234
|
+
for (const record2 of eligible) stamped.push(record2.id);
|
|
16220
16235
|
if (prepared.length > 0) await ctx.database.batch(...prepared);
|
|
16221
16236
|
});
|
|
16222
16237
|
}
|
|
@@ -16231,14 +16246,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
16231
16246
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
16232
16247
|
try {
|
|
16233
16248
|
await ctx.database.write(async (writer) => {
|
|
16234
|
-
let
|
|
16249
|
+
let record2;
|
|
16235
16250
|
try {
|
|
16236
|
-
|
|
16251
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16237
16252
|
} catch {
|
|
16238
16253
|
return;
|
|
16239
16254
|
}
|
|
16240
|
-
if (
|
|
16241
|
-
const topics = parseTopics(
|
|
16255
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
16256
|
+
const topics = parseTopics(record2.topics);
|
|
16242
16257
|
if (topics === null) return;
|
|
16243
16258
|
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
|
|
16244
16259
|
relinked.push(id);
|
|
@@ -16263,20 +16278,20 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
16263
16278
|
await ctx.database.write(async () => {
|
|
16264
16279
|
const writes = [];
|
|
16265
16280
|
for (const id of chunkIds) {
|
|
16266
|
-
let
|
|
16281
|
+
let record2;
|
|
16267
16282
|
try {
|
|
16268
|
-
|
|
16283
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16269
16284
|
} catch {
|
|
16270
16285
|
continue;
|
|
16271
16286
|
}
|
|
16272
|
-
if (
|
|
16273
|
-
if (parseTopics(
|
|
16287
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) continue;
|
|
16288
|
+
if (parseTopics(record2.topics) !== null) continue;
|
|
16274
16289
|
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb23.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
16275
16290
|
const entityIds = links.map((l) => String(l.entity_id));
|
|
16276
16291
|
if (entityIds.length === 0) continue;
|
|
16277
16292
|
const entities = await entityCtx.entityCollection.query(import_watermelondb23.Q.where("id", import_watermelondb23.Q.oneOf(entityIds))).fetch();
|
|
16278
16293
|
if (entities.length === 0) continue;
|
|
16279
|
-
const source =
|
|
16294
|
+
const source = record2.topicsUserManaged ? "user" : "auto";
|
|
16280
16295
|
const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
|
|
16281
16296
|
if (write) writes.push(write);
|
|
16282
16297
|
}
|
|
@@ -16294,7 +16309,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
16294
16309
|
if (records.length === 0) return 0;
|
|
16295
16310
|
await ctx.database.write(async () => {
|
|
16296
16311
|
const prepared = records.map(
|
|
16297
|
-
(
|
|
16312
|
+
(record2) => record2.prepareUpdate((r) => {
|
|
16298
16313
|
r._setRaw("is_deleted", true);
|
|
16299
16314
|
})
|
|
16300
16315
|
);
|
|
@@ -16339,20 +16354,20 @@ async function getDecayCandidatesRawOp(ctx) {
|
|
|
16339
16354
|
}
|
|
16340
16355
|
async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
16341
16356
|
try {
|
|
16342
|
-
const
|
|
16343
|
-
if (
|
|
16357
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16358
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16344
16359
|
let stale = false;
|
|
16345
16360
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
16346
16361
|
await ctx.database.write(async () => {
|
|
16347
|
-
if (
|
|
16362
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
16348
16363
|
stale = true;
|
|
16349
16364
|
return;
|
|
16350
16365
|
}
|
|
16351
|
-
if (opts?.expectedUpdatedAt !== void 0 &&
|
|
16366
|
+
if (opts?.expectedUpdatedAt !== void 0 && record2.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record2.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
|
|
16352
16367
|
stale = true;
|
|
16353
16368
|
return;
|
|
16354
16369
|
}
|
|
16355
|
-
await
|
|
16370
|
+
await record2.update((r) => {
|
|
16356
16371
|
r._setRaw("archived_at", archivedAtValue);
|
|
16357
16372
|
});
|
|
16358
16373
|
});
|
|
@@ -16363,15 +16378,15 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
16363
16378
|
}
|
|
16364
16379
|
async function restoreVaultMemoryOp(ctx, id) {
|
|
16365
16380
|
try {
|
|
16366
|
-
const
|
|
16367
|
-
if (
|
|
16381
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16382
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16368
16383
|
let stale = false;
|
|
16369
16384
|
await ctx.database.write(async () => {
|
|
16370
|
-
if (
|
|
16385
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
16371
16386
|
stale = true;
|
|
16372
16387
|
return;
|
|
16373
16388
|
}
|
|
16374
|
-
await
|
|
16389
|
+
await record2.update((r) => {
|
|
16375
16390
|
r._setRaw("archived_at", null);
|
|
16376
16391
|
});
|
|
16377
16392
|
});
|
|
@@ -16382,17 +16397,17 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
16382
16397
|
}
|
|
16383
16398
|
async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
16384
16399
|
try {
|
|
16385
|
-
const
|
|
16386
|
-
if (
|
|
16400
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16401
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16387
16402
|
const now = opts.now ?? Date.now();
|
|
16388
16403
|
let stale = false;
|
|
16389
16404
|
await ctx.database.write(async () => {
|
|
16390
|
-
const archivedAt =
|
|
16391
|
-
if (
|
|
16405
|
+
const archivedAt = record2.archivedAt;
|
|
16406
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
16392
16407
|
stale = true;
|
|
16393
16408
|
return;
|
|
16394
16409
|
}
|
|
16395
|
-
await
|
|
16410
|
+
await record2.update((r) => {
|
|
16396
16411
|
r._setRaw("is_deleted", true);
|
|
16397
16412
|
});
|
|
16398
16413
|
});
|
|
@@ -16410,14 +16425,14 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
16410
16425
|
}
|
|
16411
16426
|
async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel, expected) {
|
|
16412
16427
|
try {
|
|
16413
|
-
const
|
|
16414
|
-
if (
|
|
16415
|
-
const readUpdatedAt =
|
|
16416
|
-
const readStoredContent =
|
|
16428
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16429
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16430
|
+
const readUpdatedAt = record2.updatedAt.getTime();
|
|
16431
|
+
const readStoredContent = record2._getRaw("content");
|
|
16417
16432
|
if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
|
|
16418
16433
|
if (expected?.content !== void 0) {
|
|
16419
16434
|
const current = await vaultMemoryToStored(
|
|
16420
|
-
|
|
16435
|
+
record2,
|
|
16421
16436
|
ctx.walletAddress,
|
|
16422
16437
|
ctx.signMessage,
|
|
16423
16438
|
ctx.embeddedWalletSigner
|
|
@@ -16426,11 +16441,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
16426
16441
|
}
|
|
16427
16442
|
let written = false;
|
|
16428
16443
|
await ctx.database.write(async () => {
|
|
16429
|
-
if (
|
|
16430
|
-
const originalUpdatedAt =
|
|
16431
|
-
if (originalUpdatedAt !== readUpdatedAt ||
|
|
16444
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
16445
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
16446
|
+
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
16432
16447
|
return;
|
|
16433
|
-
await
|
|
16448
|
+
await record2.update((r) => {
|
|
16434
16449
|
r._setRaw("embedding", embedding);
|
|
16435
16450
|
r._setRaw("embedding_model", embeddingModel);
|
|
16436
16451
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -16445,8 +16460,8 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
16445
16460
|
function normalizeForDedupe(content) {
|
|
16446
16461
|
return content.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
16447
16462
|
}
|
|
16448
|
-
async function findQuarantinedDuplicateOp(ctx, content,
|
|
16449
|
-
const wanted = [...new Set(
|
|
16463
|
+
async function findQuarantinedDuplicateOp(ctx, content, sourceIds2, where) {
|
|
16464
|
+
const wanted = [...new Set(sourceIds2)].sort().join("\0");
|
|
16450
16465
|
const target = normalizeForDedupe(content);
|
|
16451
16466
|
const rows = await ctx.vaultMemoryCollection.query(
|
|
16452
16467
|
import_watermelondb23.Q.where("trust_tier", "quarantined"),
|
|
@@ -16465,13 +16480,13 @@ async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
|
|
|
16465
16480
|
if (!Array.isArray(ids)) continue;
|
|
16466
16481
|
const key = [...new Set(ids.filter((id) => typeof id === "string"))].sort().join("\0");
|
|
16467
16482
|
if (key !== wanted) continue;
|
|
16468
|
-
const
|
|
16483
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
16469
16484
|
raw,
|
|
16470
16485
|
ctx.walletAddress,
|
|
16471
16486
|
ctx.signMessage,
|
|
16472
16487
|
ctx.embeddedWalletSigner
|
|
16473
16488
|
);
|
|
16474
|
-
if (normalizeForDedupe(
|
|
16489
|
+
if (normalizeForDedupe(stored2.content) === target) return stored2.uniqueId;
|
|
16475
16490
|
}
|
|
16476
16491
|
return null;
|
|
16477
16492
|
}
|
|
@@ -16581,25 +16596,25 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
16581
16596
|
inserted = writable.length;
|
|
16582
16597
|
if (writable.length === 0) return;
|
|
16583
16598
|
const prepared = writable.map(
|
|
16584
|
-
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((
|
|
16585
|
-
|
|
16586
|
-
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16599
|
+
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record2) => {
|
|
16600
|
+
record2._raw.id = row.memoryId;
|
|
16601
|
+
record2._setRaw("content", content);
|
|
16602
|
+
record2._setRaw("scope", "shared");
|
|
16603
|
+
record2._setRaw("folder_id", null);
|
|
16604
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
16605
|
+
record2._setRaw("is_deleted", false);
|
|
16606
|
+
record2._setRaw("proof_count", 1);
|
|
16607
|
+
record2._setRaw("source", SOURCE_PHOTO);
|
|
16608
|
+
record2._setRaw(
|
|
16594
16609
|
"media",
|
|
16595
16610
|
row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
|
|
16596
16611
|
);
|
|
16597
|
-
|
|
16598
|
-
|
|
16612
|
+
record2._setRaw("visibility", "public");
|
|
16613
|
+
record2._setRaw("published_at", now);
|
|
16599
16614
|
if (row.eventTime) {
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16615
|
+
record2._setRaw("event_time_start", row.eventTime.start ?? null);
|
|
16616
|
+
record2._setRaw("event_time_end", row.eventTime.end ?? null);
|
|
16617
|
+
record2._setRaw("event_time_kind", row.eventTime.kind ?? null);
|
|
16603
16618
|
}
|
|
16604
16619
|
})
|
|
16605
16620
|
);
|
|
@@ -17421,11 +17436,11 @@ function folderToStored(folder) {
|
|
|
17421
17436
|
}
|
|
17422
17437
|
async function createVaultFolderOp(ctx, opts) {
|
|
17423
17438
|
const created = await ctx.database.write(async () => {
|
|
17424
|
-
return ctx.vaultFolderCollection.create((
|
|
17425
|
-
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17439
|
+
return ctx.vaultFolderCollection.create((record2) => {
|
|
17440
|
+
record2._setRaw("name", opts.name);
|
|
17441
|
+
record2._setRaw("scope", opts.scope ?? "private");
|
|
17442
|
+
record2._setRaw("is_system", opts.isSystem ?? false);
|
|
17443
|
+
record2._setRaw("is_deleted", false);
|
|
17429
17444
|
});
|
|
17430
17445
|
});
|
|
17431
17446
|
return folderToStored(created);
|
|
@@ -17436,14 +17451,14 @@ async function getAllVaultFoldersOp(ctx) {
|
|
|
17436
17451
|
}
|
|
17437
17452
|
async function updateVaultFolderOp(ctx, id, opts) {
|
|
17438
17453
|
try {
|
|
17439
|
-
const
|
|
17440
|
-
if (
|
|
17441
|
-
const scopeChanged = opts.scope !== void 0 && opts.scope !==
|
|
17454
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
17455
|
+
if (record2.isDeleted) return null;
|
|
17456
|
+
const scopeChanged = opts.scope !== void 0 && opts.scope !== record2.scope;
|
|
17442
17457
|
const updated = await ctx.database.write(async () => {
|
|
17443
17458
|
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(import_watermelondb30.Q.where("folder_id", id), import_watermelondb30.Q.where("is_deleted", false)).fetch() : [];
|
|
17444
17459
|
const updates = [];
|
|
17445
17460
|
updates.push(
|
|
17446
|
-
|
|
17461
|
+
record2.prepareUpdate((r) => {
|
|
17447
17462
|
if (opts.name !== void 0) r._setRaw("name", opts.name);
|
|
17448
17463
|
if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
|
|
17449
17464
|
})
|
|
@@ -17465,8 +17480,8 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
17465
17480
|
}
|
|
17466
17481
|
async function deleteVaultFolderOp(ctx, id) {
|
|
17467
17482
|
try {
|
|
17468
|
-
const
|
|
17469
|
-
if (
|
|
17483
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
17484
|
+
if (record2.isDeleted) return false;
|
|
17470
17485
|
await ctx.database.write(async () => {
|
|
17471
17486
|
const memories = await ctx.vaultMemoryCollection.query(import_watermelondb30.Q.where("folder_id", id), import_watermelondb30.Q.where("is_deleted", false)).fetch();
|
|
17472
17487
|
const preparedMemories = memories.map(
|
|
@@ -17475,7 +17490,7 @@ async function deleteVaultFolderOp(ctx, id) {
|
|
|
17475
17490
|
r._setRaw("scope", "private");
|
|
17476
17491
|
})
|
|
17477
17492
|
);
|
|
17478
|
-
const preparedFolder =
|
|
17493
|
+
const preparedFolder = record2.prepareUpdate((r) => {
|
|
17479
17494
|
r._setRaw("is_deleted", true);
|
|
17480
17495
|
});
|
|
17481
17496
|
await ctx.database.batch(...preparedMemories, preparedFolder);
|
|
@@ -17521,11 +17536,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
17521
17536
|
}
|
|
17522
17537
|
async function updateVaultFolderContextOp(ctx, id, context) {
|
|
17523
17538
|
try {
|
|
17524
|
-
const
|
|
17525
|
-
if (
|
|
17539
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
17540
|
+
if (record2.isDeleted) return null;
|
|
17526
17541
|
const updated = await ctx.database.write(async () => {
|
|
17527
17542
|
await ctx.database.batch(
|
|
17528
|
-
|
|
17543
|
+
record2.prepareUpdate((r) => {
|
|
17529
17544
|
r._setRaw("context", context);
|
|
17530
17545
|
})
|
|
17531
17546
|
);
|
|
@@ -19606,7 +19621,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
19606
19621
|
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
19607
19622
|
let subEmbeddings;
|
|
19608
19623
|
try {
|
|
19609
|
-
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
19624
|
+
subEmbeddings = prepared.facetEmbeddings ?? await generateEmbeddings(facetQueries, embeddingOptions);
|
|
19610
19625
|
} catch (err) {
|
|
19611
19626
|
getLogger().warn(
|
|
19612
19627
|
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
@@ -19792,6 +19807,35 @@ var DEFAULT_SCOPE = "private";
|
|
|
19792
19807
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
19793
19808
|
var DEFAULT_CONSOLIDATE_TOP_K = 20;
|
|
19794
19809
|
async function retain(content, ctx, options = {}) {
|
|
19810
|
+
return retainWithPersistence(
|
|
19811
|
+
content,
|
|
19812
|
+
{
|
|
19813
|
+
embeddingOptions: ctx.embeddingOptions,
|
|
19814
|
+
vaultCache: ctx.vaultCache,
|
|
19815
|
+
persistence: {
|
|
19816
|
+
prepare: (query, searchOptions) => prepareVaultCandidates(
|
|
19817
|
+
query,
|
|
19818
|
+
ctx.vaultCtx,
|
|
19819
|
+
ctx.embeddingOptions,
|
|
19820
|
+
ctx.vaultCache,
|
|
19821
|
+
searchOptions
|
|
19822
|
+
),
|
|
19823
|
+
get: (id) => getVaultMemoryOp(ctx.vaultCtx, id),
|
|
19824
|
+
tombstones: (_embedding, _model, scope, folderId) => getAllVaultMemoriesOp(ctx.vaultCtx, {
|
|
19825
|
+
includeDeleted: true,
|
|
19826
|
+
scopes: [scope],
|
|
19827
|
+
...folderId !== void 0 && { folderId }
|
|
19828
|
+
}),
|
|
19829
|
+
create: (input) => createVaultMemoryOp(ctx.vaultCtx, input),
|
|
19830
|
+
update: (id, patch) => updateVaultMemoryOp(ctx.vaultCtx, id, patch),
|
|
19831
|
+
supersede: (id, successor) => supersedeVaultMemoryOp(ctx.vaultCtx, id, successor),
|
|
19832
|
+
createSuperseding: (input, target) => createSupersedingMemoryOp(ctx.vaultCtx, input, target)
|
|
19833
|
+
}
|
|
19834
|
+
},
|
|
19835
|
+
options
|
|
19836
|
+
);
|
|
19837
|
+
}
|
|
19838
|
+
async function retainWithPersistence(content, ctx, options = {}) {
|
|
19795
19839
|
const trimmed = content.trim();
|
|
19796
19840
|
if (trimmed.length === 0) {
|
|
19797
19841
|
throw new Error("retain: content cannot be empty");
|
|
@@ -19804,19 +19848,13 @@ async function retain(content, ctx, options = {}) {
|
|
|
19804
19848
|
let supersedeContent;
|
|
19805
19849
|
let prepared;
|
|
19806
19850
|
if (enableAutoMerge) {
|
|
19807
|
-
prepared = await
|
|
19808
|
-
|
|
19809
|
-
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
{
|
|
19813
|
-
|
|
19814
|
-
useFusion: false,
|
|
19815
|
-
scopes: [resolvedScope],
|
|
19816
|
-
includeArchived: true,
|
|
19817
|
-
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
19818
|
-
}
|
|
19819
|
-
);
|
|
19851
|
+
prepared = await ctx.persistence.prepare(trimmed, {
|
|
19852
|
+
limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
|
|
19853
|
+
useFusion: false,
|
|
19854
|
+
scopes: [resolvedScope],
|
|
19855
|
+
includeArchived: true,
|
|
19856
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
19857
|
+
});
|
|
19820
19858
|
if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
|
|
19821
19859
|
throw new Error(
|
|
19822
19860
|
"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."
|
|
@@ -19847,7 +19885,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19847
19885
|
);
|
|
19848
19886
|
if (matches.length > 0) {
|
|
19849
19887
|
const targetId = matches[0].uniqueId;
|
|
19850
|
-
const existing = await
|
|
19888
|
+
const existing = await ctx.persistence.get(targetId);
|
|
19851
19889
|
if (existing && !existing.supersededBy) {
|
|
19852
19890
|
const mergedSourceIds = unionStrings(
|
|
19853
19891
|
existing.sourceChunkIds ?? [],
|
|
@@ -19856,7 +19894,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19856
19894
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
19857
19895
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
19858
19896
|
const resurrect = resurrectFields(existing);
|
|
19859
|
-
const updated = await
|
|
19897
|
+
const updated = await ctx.persistence.update(targetId, {
|
|
19860
19898
|
content: existing.content,
|
|
19861
19899
|
proofCountIncrement: 1,
|
|
19862
19900
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -19883,7 +19921,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
19883
19921
|
}
|
|
19884
19922
|
const contentToWrite = supersedeContent ?? trimmed;
|
|
19885
19923
|
const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
|
|
19886
|
-
const
|
|
19924
|
+
const generatedEmbedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
19925
|
+
const embedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
19887
19926
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19888
19927
|
if (options.respectTombstones) {
|
|
19889
19928
|
const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
@@ -19923,8 +19962,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19923
19962
|
};
|
|
19924
19963
|
if (supersedeTargetIds.length > 0) {
|
|
19925
19964
|
const [primaryTargetId, ...restTargetIds] = supersedeTargetIds;
|
|
19926
|
-
const { created: created2, retired } = await
|
|
19927
|
-
ctx.vaultCtx,
|
|
19965
|
+
const { created: created2, retired } = await ctx.persistence.createSuperseding(
|
|
19928
19966
|
createOpts,
|
|
19929
19967
|
primaryTargetId
|
|
19930
19968
|
);
|
|
@@ -19940,11 +19978,11 @@ async function retain(content, ctx, options = {}) {
|
|
|
19940
19978
|
for (const staleId of restTargetIds) {
|
|
19941
19979
|
let ok = false;
|
|
19942
19980
|
try {
|
|
19943
|
-
ok = await
|
|
19981
|
+
ok = await ctx.persistence.supersede(staleId, created2.uniqueId) === true;
|
|
19944
19982
|
} catch {
|
|
19945
19983
|
}
|
|
19946
19984
|
if (ok) continue;
|
|
19947
|
-
const stillLive = await
|
|
19985
|
+
const stillLive = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(staleId) : ctx.persistence.get(staleId)).catch(() => null);
|
|
19948
19986
|
if (stillLive && !stillLive.supersededBy) liveLeftovers.push(staleId);
|
|
19949
19987
|
}
|
|
19950
19988
|
if (liveLeftovers.length > 0) {
|
|
@@ -19971,7 +20009,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19971
20009
|
`supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
|
|
19972
20010
|
);
|
|
19973
20011
|
}
|
|
19974
|
-
const created = await
|
|
20012
|
+
const created = await ctx.persistence.create(createOpts);
|
|
19975
20013
|
cacheRowVector(
|
|
19976
20014
|
ctx.vaultCache,
|
|
19977
20015
|
created.uniqueId,
|
|
@@ -19990,11 +20028,7 @@ function unionStrings(a, b) {
|
|
|
19990
20028
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
19991
20029
|
}
|
|
19992
20030
|
async function findTombstoneMatch(embedding, embeddingModel, scope, ctx, opts) {
|
|
19993
|
-
const rows = await
|
|
19994
|
-
includeDeleted: true,
|
|
19995
|
-
scopes: [scope],
|
|
19996
|
-
...opts.folderId !== void 0 && { folderId: opts.folderId }
|
|
19997
|
-
});
|
|
20031
|
+
const rows = await ctx.persistence.tombstones(embedding, embeddingModel, scope, opts.folderId);
|
|
19998
20032
|
let bestId = null;
|
|
19999
20033
|
let bestSim = opts.threshold;
|
|
20000
20034
|
for (const row of rows) {
|
|
@@ -20061,7 +20095,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20061
20095
|
if (requestedIds.length === 0) return null;
|
|
20062
20096
|
const valid = [];
|
|
20063
20097
|
for (const id of requestedIds) {
|
|
20064
|
-
const existing = await
|
|
20098
|
+
const existing = await ctx.persistence.get(id);
|
|
20065
20099
|
if (existing && !existing.supersededBy) valid.push(id);
|
|
20066
20100
|
}
|
|
20067
20101
|
if (valid.length === 0) {
|
|
@@ -20073,7 +20107,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20073
20107
|
return { supersede: valid, content: decision.content };
|
|
20074
20108
|
}
|
|
20075
20109
|
if (decision.action === "noop" && decision.targetId) {
|
|
20076
|
-
const existing = await
|
|
20110
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
20077
20111
|
if (!existing || existing.supersededBy) {
|
|
20078
20112
|
return abandonToRace(
|
|
20079
20113
|
options,
|
|
@@ -20087,7 +20121,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20087
20121
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
20088
20122
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
20089
20123
|
const resurrect = resurrectFields(existing);
|
|
20090
|
-
const updated = await
|
|
20124
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
20091
20125
|
content: existing.content,
|
|
20092
20126
|
proofCountIncrement: 1,
|
|
20093
20127
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -20115,7 +20149,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20115
20149
|
};
|
|
20116
20150
|
}
|
|
20117
20151
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
20118
|
-
const existing = await
|
|
20152
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
20119
20153
|
if (!existing || existing.supersededBy) {
|
|
20120
20154
|
return abandonToRace(
|
|
20121
20155
|
options,
|
|
@@ -20126,12 +20160,13 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20126
20160
|
existing.sourceChunkIds ?? [],
|
|
20127
20161
|
options.sourceChunkIds ?? []
|
|
20128
20162
|
);
|
|
20129
|
-
const
|
|
20163
|
+
const generatedEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
|
|
20164
|
+
const newEmbedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
20130
20165
|
const consolidatedModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
20131
20166
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
20132
20167
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
20133
20168
|
const resurrect = resurrectFields(existing);
|
|
20134
|
-
const updated = await
|
|
20169
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
20135
20170
|
content: decision.content,
|
|
20136
20171
|
proofCountIncrement: 1,
|
|
20137
20172
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -20175,7 +20210,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20175
20210
|
return null;
|
|
20176
20211
|
}
|
|
20177
20212
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
20178
|
-
const stillExists = await
|
|
20213
|
+
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
20179
20214
|
if (stillExists) {
|
|
20180
20215
|
throw new Error(`retain: merge into memory ${targetId} failed to persist`);
|
|
20181
20216
|
}
|
|
@@ -20692,9 +20727,9 @@ function createAutoExtractor(options) {
|
|
|
20692
20727
|
const persistCursor = (conversationId, messages, advancedToId, contiguous) => {
|
|
20693
20728
|
if (!cursorStore || conversationId === void 0 || !contiguous) return;
|
|
20694
20729
|
try {
|
|
20695
|
-
const
|
|
20696
|
-
if (
|
|
20697
|
-
const storedIdx = messages.findIndex((m) => m.id ===
|
|
20730
|
+
const stored2 = cursorStore.get(conversationId);
|
|
20731
|
+
if (stored2 && stored2 !== advancedToId) {
|
|
20732
|
+
const storedIdx = messages.findIndex((m) => m.id === stored2);
|
|
20698
20733
|
const newIdx = messages.findIndex((m) => m.id === advancedToId);
|
|
20699
20734
|
if (storedIdx !== -1 && newIdx !== -1 && storedIdx >= newIdx) return;
|
|
20700
20735
|
}
|
|
@@ -21674,7 +21709,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21674
21709
|
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
21675
21710
|
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
21676
21711
|
if (chunksScopeRestricted) degraded.push("chunks-scope-restricted");
|
|
21677
|
-
const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
|
|
21712
|
+
const laneRan = types.includes("fact") && (!!ctx.factSource || !!ctx.vaultCtx && !!ctx.vaultCache) || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
|
|
21678
21713
|
const scores = admitted.map((m) => m.score);
|
|
21679
21714
|
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
21680
21715
|
const diagnostics = {
|
|
@@ -21716,7 +21751,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21716
21751
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
21717
21752
|
}
|
|
21718
21753
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
21719
|
-
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
21754
|
+
const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
|
|
21720
21755
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
21721
21756
|
const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
|
|
21722
21757
|
const prepStart = nowMs2();
|
|
@@ -21746,7 +21781,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21746
21781
|
safeLane(
|
|
21747
21782
|
"graph",
|
|
21748
21783
|
() => graphLaneFailed = true,
|
|
21749
|
-
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
21784
|
+
() => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
21750
21785
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
21751
21786
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
21752
21787
|
...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
|
|
@@ -21757,13 +21792,13 @@ async function recall(query, ctx, options = {}) {
|
|
|
21757
21792
|
wantsTemporal ? safeLane(
|
|
21758
21793
|
"temporal",
|
|
21759
21794
|
() => temporalLaneFailed = true,
|
|
21760
|
-
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
21795
|
+
() => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
21761
21796
|
) : Promise.resolve([])
|
|
21762
21797
|
]);
|
|
21763
21798
|
prepMs = nowMs2() - prepStart;
|
|
21764
21799
|
graphLaneCount = entityRanking.length;
|
|
21765
21800
|
temporalLaneCount = temporalRanking.length;
|
|
21766
|
-
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
21801
|
+
if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
|
|
21767
21802
|
const factStart = nowMs2();
|
|
21768
21803
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
21769
21804
|
factFloor = vaultMinScore;
|
|
@@ -21779,50 +21814,50 @@ async function recall(query, ctx, options = {}) {
|
|
|
21779
21814
|
rankedOnCosine: factRankedOnCosine,
|
|
21780
21815
|
decryptLast: factDecryptLast,
|
|
21781
21816
|
rowsDecrypted: factRowsDecrypted
|
|
21782
|
-
} = await searchVaultMemoriesWithSize(
|
|
21783
|
-
|
|
21817
|
+
} = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
|
|
21818
|
+
searchQuery,
|
|
21784
21819
|
ctx.vaultCtx,
|
|
21785
21820
|
ctx.embeddingOptions,
|
|
21786
21821
|
ctx.vaultCache,
|
|
21787
|
-
|
|
21788
|
-
|
|
21789
|
-
|
|
21790
|
-
|
|
21791
|
-
|
|
21792
|
-
|
|
21793
|
-
|
|
21794
|
-
|
|
21795
|
-
|
|
21796
|
-
|
|
21797
|
-
|
|
21798
|
-
|
|
21799
|
-
|
|
21800
|
-
|
|
21801
|
-
|
|
21802
|
-
|
|
21803
|
-
|
|
21804
|
-
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
21813
|
-
|
|
21814
|
-
|
|
21815
|
-
|
|
21816
|
-
|
|
21817
|
-
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
21821
|
-
|
|
21822
|
-
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
);
|
|
21822
|
+
searchOptions
|
|
21823
|
+
)))(query, {
|
|
21824
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
21825
|
+
minSimilarity: vaultMinScore,
|
|
21826
|
+
useFusion: true,
|
|
21827
|
+
rerank: flags.rerank,
|
|
21828
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
21829
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
21830
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
21831
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
21832
|
+
},
|
|
21833
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
21834
|
+
...options.recency && { recency: options.recency },
|
|
21835
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
21836
|
+
...options.supersessionBoost !== void 0 && {
|
|
21837
|
+
supersessionBoost: options.supersessionBoost
|
|
21838
|
+
},
|
|
21839
|
+
...options.supersessionWindow !== void 0 && {
|
|
21840
|
+
supersessionWindow: options.supersessionWindow
|
|
21841
|
+
},
|
|
21842
|
+
...options.proofCountAlpha !== void 0 && {
|
|
21843
|
+
proofCountAlpha: options.proofCountAlpha
|
|
21844
|
+
},
|
|
21845
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
21846
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
21847
|
+
},
|
|
21848
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
21849
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
21850
|
+
...subQueries && { subQueries },
|
|
21851
|
+
...options.scopes && { scopes: options.scopes },
|
|
21852
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
21853
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
21854
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
21855
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
21856
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
21857
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
21858
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
21859
|
+
queryEmbedTotalTimeoutMs
|
|
21860
|
+
});
|
|
21826
21861
|
factResults.push(
|
|
21827
21862
|
...dedupeBy(
|
|
21828
21863
|
results,
|
|
@@ -22635,26 +22670,26 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
22635
22670
|
};
|
|
22636
22671
|
const inputs = [];
|
|
22637
22672
|
for (const id of new Set(memoryIds)) {
|
|
22638
|
-
let
|
|
22673
|
+
let record2;
|
|
22639
22674
|
try {
|
|
22640
|
-
|
|
22675
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
22641
22676
|
} catch (err) {
|
|
22642
22677
|
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
22643
22678
|
skip(id, "not-found");
|
|
22644
22679
|
continue;
|
|
22645
22680
|
}
|
|
22646
|
-
if (
|
|
22681
|
+
if (record2.isDeleted || ctx.userId !== void 0 && record2.userId !== ctx.userId || record2.topicsUserManaged) {
|
|
22647
22682
|
skip(id, "excluded");
|
|
22648
22683
|
continue;
|
|
22649
22684
|
}
|
|
22650
22685
|
try {
|
|
22651
|
-
const
|
|
22652
|
-
|
|
22686
|
+
const stored2 = await vaultMemoryToStored(
|
|
22687
|
+
record2,
|
|
22653
22688
|
ctx.walletAddress,
|
|
22654
22689
|
ctx.signMessage,
|
|
22655
22690
|
ctx.embeddedWalletSigner
|
|
22656
22691
|
);
|
|
22657
|
-
inputs.push({ id, content:
|
|
22692
|
+
inputs.push({ id, content: stored2.content });
|
|
22658
22693
|
} catch (err) {
|
|
22659
22694
|
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
22660
22695
|
skip(id, "unreadable");
|
|
@@ -22839,6 +22874,774 @@ function createLocalMemoryStore(options) {
|
|
|
22839
22874
|
};
|
|
22840
22875
|
}
|
|
22841
22876
|
|
|
22877
|
+
// src/lib/memory/store/remotePersistence.ts
|
|
22878
|
+
var RemoteMemoryError = class extends Error {
|
|
22879
|
+
constructor(message, status, code) {
|
|
22880
|
+
super(message);
|
|
22881
|
+
this.status = status;
|
|
22882
|
+
this.code = code;
|
|
22883
|
+
this.name = "RemoteMemoryError";
|
|
22884
|
+
}
|
|
22885
|
+
};
|
|
22886
|
+
var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
|
|
22887
|
+
var memoryFields = {
|
|
22888
|
+
memory_id: true,
|
|
22889
|
+
content: true,
|
|
22890
|
+
scope: true,
|
|
22891
|
+
created_at: true,
|
|
22892
|
+
updated_at: true,
|
|
22893
|
+
is_deleted: true,
|
|
22894
|
+
embedding: true,
|
|
22895
|
+
embedding_model: true,
|
|
22896
|
+
kind: true,
|
|
22897
|
+
kind_value: true,
|
|
22898
|
+
level: true,
|
|
22899
|
+
folder_id: true,
|
|
22900
|
+
source_chunk_ids: true,
|
|
22901
|
+
proof_count: true,
|
|
22902
|
+
source: true,
|
|
22903
|
+
event_time_start: true,
|
|
22904
|
+
event_time_end: true,
|
|
22905
|
+
event_time_kind: true,
|
|
22906
|
+
topics_user_managed: true,
|
|
22907
|
+
topics: true,
|
|
22908
|
+
topics_updated_at: true,
|
|
22909
|
+
media: true,
|
|
22910
|
+
topics_extracted_at: true,
|
|
22911
|
+
topics_extracted_version: true,
|
|
22912
|
+
superseded_by: true,
|
|
22913
|
+
superseded_at: true,
|
|
22914
|
+
last_observed_at: true,
|
|
22915
|
+
fact_type: true,
|
|
22916
|
+
archived_at: true,
|
|
22917
|
+
trust_tier: true,
|
|
22918
|
+
visibility: true,
|
|
22919
|
+
twin_opt_in: true,
|
|
22920
|
+
published_at: true,
|
|
22921
|
+
geohash: true
|
|
22922
|
+
};
|
|
22923
|
+
var candidateListLimits = [
|
|
22924
|
+
["scopes", 20],
|
|
22925
|
+
["fact_types", 20],
|
|
22926
|
+
["memory_ids", 1e3],
|
|
22927
|
+
["force_ids", 100]
|
|
22928
|
+
];
|
|
22929
|
+
function record(value) {
|
|
22930
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22931
|
+
}
|
|
22932
|
+
function memoryRecord(value) {
|
|
22933
|
+
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))) {
|
|
22934
|
+
throw new Error("Invalid nearby private-memory response");
|
|
22935
|
+
}
|
|
22936
|
+
return value;
|
|
22937
|
+
}
|
|
22938
|
+
async function createRemoteMemoryPersistence(options) {
|
|
22939
|
+
const base = new URL(options.baseUrl);
|
|
22940
|
+
if (!/^https?:$/.test(base.protocol) || base.username || base.password || base.search || base.hash) {
|
|
22941
|
+
throw new Error(
|
|
22942
|
+
"baseUrl must be an HTTP(S) origin or base path without credentials, query or fragment"
|
|
22943
|
+
);
|
|
22944
|
+
}
|
|
22945
|
+
if (!options.keyId || options.keyId.length > 256)
|
|
22946
|
+
throw new Error("A canonical keyId is required");
|
|
22947
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
22948
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
22949
|
+
throw new Error("timeoutMs must be a positive number");
|
|
22950
|
+
const root = base.href.replace(/\/$/, "") + "/api/private-memories";
|
|
22951
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
22952
|
+
const request = async (path, init = {}, signal) => {
|
|
22953
|
+
const controller = new AbortController();
|
|
22954
|
+
let timedOut = false;
|
|
22955
|
+
const timer = setTimeout(() => {
|
|
22956
|
+
timedOut = true;
|
|
22957
|
+
controller.abort();
|
|
22958
|
+
}, timeoutMs);
|
|
22959
|
+
const forwardAbort = () => controller.abort(signal?.reason);
|
|
22960
|
+
if (signal?.aborted) forwardAbort();
|
|
22961
|
+
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
22962
|
+
let rejectAborted;
|
|
22963
|
+
const aborted = new Promise((_, reject) => {
|
|
22964
|
+
rejectAborted = () => reject(
|
|
22965
|
+
controller.signal.reason instanceof Error ? controller.signal.reason : new Error("Nearby request aborted")
|
|
22966
|
+
);
|
|
22967
|
+
if (controller.signal.aborted) rejectAborted();
|
|
22968
|
+
else controller.signal.addEventListener("abort", rejectAborted, { once: true });
|
|
22969
|
+
});
|
|
22970
|
+
aborted.catch(() => void 0);
|
|
22971
|
+
try {
|
|
22972
|
+
const token = await Promise.race([options.getToken(), aborted]);
|
|
22973
|
+
if (controller.signal.aborted) await aborted;
|
|
22974
|
+
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
22975
|
+
const response = await fetcher(root + path, {
|
|
22976
|
+
...init,
|
|
22977
|
+
headers: {
|
|
22978
|
+
Authorization: `Bearer ${token}`,
|
|
22979
|
+
...init.body ? { "Content-Type": "application/json" } : {}
|
|
22980
|
+
},
|
|
22981
|
+
redirect: "error",
|
|
22982
|
+
signal: controller.signal
|
|
22983
|
+
});
|
|
22984
|
+
if (!response.ok) {
|
|
22985
|
+
const body = await response.json().catch(() => null);
|
|
22986
|
+
throw new RemoteMemoryError(
|
|
22987
|
+
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
22988
|
+
response.status,
|
|
22989
|
+
record(body) && typeof body.code === "string" ? body.code : void 0
|
|
22990
|
+
);
|
|
22991
|
+
}
|
|
22992
|
+
return await response.json();
|
|
22993
|
+
} catch (error) {
|
|
22994
|
+
if (timedOut) throw new RemoteMemoryError("Nearby request timed out", 408, "timeout");
|
|
22995
|
+
throw error;
|
|
22996
|
+
} finally {
|
|
22997
|
+
clearTimeout(timer);
|
|
22998
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
22999
|
+
if (rejectAborted) controller.signal.removeEventListener("abort", rejectAborted);
|
|
23000
|
+
}
|
|
23001
|
+
};
|
|
23002
|
+
const account = await request("/account", {}, options.signal);
|
|
23003
|
+
if (!record(account) || account.state !== "active") {
|
|
23004
|
+
throw new RemoteMemoryError(
|
|
23005
|
+
"Complete and verify migration before using remote memories",
|
|
23006
|
+
409,
|
|
23007
|
+
"memory_not_active"
|
|
23008
|
+
);
|
|
23009
|
+
}
|
|
23010
|
+
if (account.key_id !== options.keyId) {
|
|
23011
|
+
throw new RemoteMemoryError(
|
|
23012
|
+
"The canonical memory key does not match this account",
|
|
23013
|
+
409,
|
|
23014
|
+
"key_mismatch"
|
|
23015
|
+
);
|
|
23016
|
+
}
|
|
23017
|
+
const snapshots = /* @__PURE__ */ new WeakMap();
|
|
23018
|
+
const decode = async (value) => {
|
|
23019
|
+
const item = memoryRecord(value);
|
|
23020
|
+
const decrypt = async (ciphertext) => {
|
|
23021
|
+
if (!ciphertextPattern.test(ciphertext))
|
|
23022
|
+
throw new Error("Nearby returned unencrypted memory content");
|
|
23023
|
+
const plaintext = await options.decrypt(ciphertext);
|
|
23024
|
+
if (plaintext === ciphertext) throw new Error("Memory decryption failed");
|
|
23025
|
+
return plaintext;
|
|
23026
|
+
};
|
|
23027
|
+
const decoded = {
|
|
23028
|
+
...item,
|
|
23029
|
+
memory: {
|
|
23030
|
+
...item.memory,
|
|
23031
|
+
content: await decrypt(item.memory.content),
|
|
23032
|
+
...item.memory.kind_value !== void 0 && {
|
|
23033
|
+
kind_value: await decrypt(item.memory.kind_value)
|
|
23034
|
+
}
|
|
23035
|
+
}
|
|
23036
|
+
};
|
|
23037
|
+
return remember(decoded, item);
|
|
23038
|
+
};
|
|
23039
|
+
const remember = (decoded, item) => {
|
|
23040
|
+
snapshots.set(decoded, {
|
|
23041
|
+
id: item.memory.memory_id,
|
|
23042
|
+
version: item.version,
|
|
23043
|
+
content: decoded.memory.content,
|
|
23044
|
+
kindValue: decoded.memory.kind_value,
|
|
23045
|
+
encryptedContent: item.memory.content,
|
|
23046
|
+
encryptedKindValue: item.memory.kind_value
|
|
23047
|
+
});
|
|
23048
|
+
return decoded;
|
|
23049
|
+
};
|
|
23050
|
+
const decodeAll = async (values) => {
|
|
23051
|
+
const records = values.map(memoryRecord);
|
|
23052
|
+
const settled = await Promise.allSettled(records.map(decode));
|
|
23053
|
+
const items = [];
|
|
23054
|
+
const failed = [];
|
|
23055
|
+
settled.forEach((result, i) => {
|
|
23056
|
+
if (result.status === "fulfilled") items.push(result.value);
|
|
23057
|
+
else
|
|
23058
|
+
failed.push({
|
|
23059
|
+
memory_id: records[i].memory.memory_id,
|
|
23060
|
+
version: records[i].version,
|
|
23061
|
+
error: result.reason instanceof Error ? result.reason : new Error(String(result.reason))
|
|
23062
|
+
});
|
|
23063
|
+
});
|
|
23064
|
+
return { items, failed };
|
|
23065
|
+
};
|
|
23066
|
+
const decodeCommitted = async (value, write) => {
|
|
23067
|
+
const item = memoryRecord(value);
|
|
23068
|
+
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)
|
|
23069
|
+
return decode(item);
|
|
23070
|
+
return remember(
|
|
23071
|
+
{
|
|
23072
|
+
...item,
|
|
23073
|
+
memory: {
|
|
23074
|
+
...item.memory,
|
|
23075
|
+
content: write.content,
|
|
23076
|
+
...write.kindValue !== void 0 && { kind_value: write.kindValue }
|
|
23077
|
+
}
|
|
23078
|
+
},
|
|
23079
|
+
item
|
|
23080
|
+
);
|
|
23081
|
+
};
|
|
23082
|
+
const encryptField2 = async (plaintext) => {
|
|
23083
|
+
const ciphertext = await options.encrypt(plaintext);
|
|
23084
|
+
if (ciphertext === plaintext || !ciphertextPattern.test(ciphertext))
|
|
23085
|
+
throw new Error("Field encryption must return SDK ciphertext; refusing to upload plaintext");
|
|
23086
|
+
return ciphertext;
|
|
23087
|
+
};
|
|
23088
|
+
const memoryPath = (id) => {
|
|
23089
|
+
if (!id || id.length > 128) throw new Error("memory_id must be 1\u2013128 characters");
|
|
23090
|
+
return "/memories/" + encodeURIComponent(id);
|
|
23091
|
+
};
|
|
23092
|
+
const prepareWrite = async (memory, expectedVersion, signal) => {
|
|
23093
|
+
const unknown = Object.keys(memory).filter(
|
|
23094
|
+
(key) => !Object.prototype.hasOwnProperty.call(memoryFields, key)
|
|
23095
|
+
);
|
|
23096
|
+
if (unknown.length) {
|
|
23097
|
+
throw new RemoteMemoryError(
|
|
23098
|
+
`Unknown private-memory fields (${unknown.join(", ")}); refusing to forward them`,
|
|
23099
|
+
400,
|
|
23100
|
+
"unknown_field"
|
|
23101
|
+
);
|
|
23102
|
+
}
|
|
23103
|
+
memory = { ...memory, ...memory.embedding && { embedding: [...memory.embedding] } };
|
|
23104
|
+
const path = memoryPath(memory.memory_id);
|
|
23105
|
+
const snapshot = typeof expectedVersion === "number" ? void 0 : snapshots.get(expectedVersion);
|
|
23106
|
+
if (typeof expectedVersion !== "number" && (!snapshot || snapshot.id !== memory.memory_id || snapshot.version !== expectedVersion.version))
|
|
23107
|
+
throw new Error(
|
|
23108
|
+
"Expected snapshot must be an unmodified version from this persistence instance"
|
|
23109
|
+
);
|
|
23110
|
+
expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
|
|
23111
|
+
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
23112
|
+
throw new Error("expectedVersion must be a nonnegative integer");
|
|
23113
|
+
const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
|
|
23114
|
+
let existing;
|
|
23115
|
+
if (expectedVersion !== 0 && !snapshot) {
|
|
23116
|
+
try {
|
|
23117
|
+
existing = memoryRecord(await request(path, {}, signal));
|
|
23118
|
+
} catch (error) {
|
|
23119
|
+
if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
|
|
23120
|
+
throw error;
|
|
23121
|
+
}
|
|
23122
|
+
}
|
|
23123
|
+
if (existing && existing.version !== expectedVersion) throw conflict();
|
|
23124
|
+
const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
|
|
23125
|
+
const content = (snapshot?.content ?? decoded?.memory.content) === memory.content ? snapshot?.encryptedContent ?? existing.memory.content : await encryptField2(memory.content);
|
|
23126
|
+
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);
|
|
23127
|
+
return {
|
|
23128
|
+
body: {
|
|
23129
|
+
expected_version: expectedVersion,
|
|
23130
|
+
memory: { ...memory, content, ...kindValue !== void 0 && { kind_value: kindValue } }
|
|
23131
|
+
},
|
|
23132
|
+
content: memory.content,
|
|
23133
|
+
kindValue: memory.kind_value
|
|
23134
|
+
};
|
|
23135
|
+
};
|
|
23136
|
+
const fetchCandidates = async (embedding, candidateOptions, withCounts) => {
|
|
23137
|
+
const limit = candidateOptions.limit ?? 100;
|
|
23138
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
23139
|
+
throw new Error("Candidate limit must be 1\u2013100");
|
|
23140
|
+
for (const [key, max] of candidateListLimits) {
|
|
23141
|
+
const values = candidateOptions[key];
|
|
23142
|
+
if (values && values.length > max)
|
|
23143
|
+
throw new Error(`Candidate ${key} accepts at most ${max} entries (got ${values.length})`);
|
|
23144
|
+
}
|
|
23145
|
+
const result = await request(
|
|
23146
|
+
"/candidates",
|
|
23147
|
+
{
|
|
23148
|
+
method: "POST",
|
|
23149
|
+
body: JSON.stringify({
|
|
23150
|
+
embedding,
|
|
23151
|
+
limit,
|
|
23152
|
+
force_ids: candidateOptions.force_ids ?? [],
|
|
23153
|
+
...withCounts && { with_counts: true },
|
|
23154
|
+
...Object.fromEntries(
|
|
23155
|
+
[
|
|
23156
|
+
"scopes",
|
|
23157
|
+
"memory_ids",
|
|
23158
|
+
"embedding_model",
|
|
23159
|
+
"strict_model",
|
|
23160
|
+
"include_deleted",
|
|
23161
|
+
"deleted_only"
|
|
23162
|
+
].filter(
|
|
23163
|
+
(key) => candidateOptions[key] !== void 0
|
|
23164
|
+
).map((key) => [key, candidateOptions[key]])
|
|
23165
|
+
),
|
|
23166
|
+
...candidateOptions.fact_types !== void 0 && {
|
|
23167
|
+
fact_types: candidateOptions.fact_types
|
|
23168
|
+
},
|
|
23169
|
+
...candidateOptions.include_archived !== void 0 && {
|
|
23170
|
+
include_archived: candidateOptions.include_archived
|
|
23171
|
+
},
|
|
23172
|
+
...candidateOptions.include_quarantined !== void 0 && {
|
|
23173
|
+
include_quarantined: candidateOptions.include_quarantined
|
|
23174
|
+
},
|
|
23175
|
+
...candidateOptions.include_superseded !== void 0 && {
|
|
23176
|
+
include_superseded: candidateOptions.include_superseded
|
|
23177
|
+
}
|
|
23178
|
+
})
|
|
23179
|
+
},
|
|
23180
|
+
candidateOptions.signal
|
|
23181
|
+
);
|
|
23182
|
+
if (!record(result) || !Array.isArray(result.items))
|
|
23183
|
+
throw new Error("Invalid nearby candidate response");
|
|
23184
|
+
return result;
|
|
23185
|
+
};
|
|
23186
|
+
const candidateSet = async (embedding, candidateOptions = {}) => {
|
|
23187
|
+
const result = await fetchCandidates(embedding, candidateOptions, true);
|
|
23188
|
+
if (!Number.isSafeInteger(result.total_count) || result.total_count < 0 || !Number.isSafeInteger(result.unavailable_count) || result.unavailable_count < 0)
|
|
23189
|
+
throw new Error("Invalid nearby candidate response");
|
|
23190
|
+
return {
|
|
23191
|
+
...await decodeAll(result.items),
|
|
23192
|
+
total_count: result.total_count,
|
|
23193
|
+
unavailable_count: result.unavailable_count
|
|
23194
|
+
};
|
|
23195
|
+
};
|
|
23196
|
+
return {
|
|
23197
|
+
get: async (id, signal) => {
|
|
23198
|
+
try {
|
|
23199
|
+
return await decode(await request(memoryPath(id), {}, signal));
|
|
23200
|
+
} catch (error) {
|
|
23201
|
+
if (error instanceof RemoteMemoryError && error.status === 404) return null;
|
|
23202
|
+
throw error;
|
|
23203
|
+
}
|
|
23204
|
+
},
|
|
23205
|
+
list: async (listOptions = {}) => {
|
|
23206
|
+
const { signal, ...query } = listOptions;
|
|
23207
|
+
if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200)) {
|
|
23208
|
+
throw new Error("Page limit must be 1\u2013200");
|
|
23209
|
+
}
|
|
23210
|
+
const params = new URLSearchParams();
|
|
23211
|
+
for (const key of [
|
|
23212
|
+
"cursor",
|
|
23213
|
+
"limit",
|
|
23214
|
+
"include_deleted",
|
|
23215
|
+
"include_archived",
|
|
23216
|
+
"include_quarantined",
|
|
23217
|
+
"include_superseded",
|
|
23218
|
+
"include_embeddings"
|
|
23219
|
+
]) {
|
|
23220
|
+
if (query[key] !== void 0) params.set(key, String(query[key]));
|
|
23221
|
+
}
|
|
23222
|
+
const page = await request("/memories?" + params.toString(), {}, signal);
|
|
23223
|
+
if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
|
|
23224
|
+
throw new Error("Invalid nearby private-memory page");
|
|
23225
|
+
}
|
|
23226
|
+
return {
|
|
23227
|
+
...await decodeAll(page.items),
|
|
23228
|
+
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
|
|
23229
|
+
};
|
|
23230
|
+
},
|
|
23231
|
+
put: async (memory, expectedVersion, signal) => {
|
|
23232
|
+
const write = await prepareWrite(memory, expectedVersion, signal);
|
|
23233
|
+
return decodeCommitted(
|
|
23234
|
+
await request(
|
|
23235
|
+
memoryPath(write.body.memory.memory_id),
|
|
23236
|
+
{
|
|
23237
|
+
method: "PUT",
|
|
23238
|
+
body: JSON.stringify({ key_id: options.keyId, ...write.body })
|
|
23239
|
+
},
|
|
23240
|
+
signal
|
|
23241
|
+
),
|
|
23242
|
+
write
|
|
23243
|
+
);
|
|
23244
|
+
},
|
|
23245
|
+
putMany: async (writes, signal) => {
|
|
23246
|
+
if (writes.length < 1 || writes.length > 50 || new Set(writes.map((w) => w.memory.memory_id)).size !== writes.length)
|
|
23247
|
+
throw new Error("Batch must contain 1\u201350 distinct memory ids");
|
|
23248
|
+
const prepared = await Promise.all(
|
|
23249
|
+
writes.map((w) => prepareWrite(w.memory, w.expectedVersion, signal))
|
|
23250
|
+
);
|
|
23251
|
+
const result = await request(
|
|
23252
|
+
"/memories/batch",
|
|
23253
|
+
{
|
|
23254
|
+
method: "POST",
|
|
23255
|
+
body: JSON.stringify({ key_id: options.keyId, writes: prepared.map((w) => w.body) })
|
|
23256
|
+
},
|
|
23257
|
+
signal
|
|
23258
|
+
);
|
|
23259
|
+
if (!record(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
|
|
23260
|
+
throw new Error("Invalid nearby batch response");
|
|
23261
|
+
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
23262
|
+
},
|
|
23263
|
+
candidateSet,
|
|
23264
|
+
candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
|
|
23265
|
+
};
|
|
23266
|
+
}
|
|
23267
|
+
|
|
23268
|
+
// src/lib/memory/store/remotePipeline.ts
|
|
23269
|
+
var import_uuid5 = require("uuid");
|
|
23270
|
+
init_logger();
|
|
23271
|
+
function storedVector(vector) {
|
|
23272
|
+
if (!Array.isArray(vector) || vector.length !== 1536 && vector.length !== 4096 || vector.some((v) => !Number.isFinite(v)))
|
|
23273
|
+
throw new Error("Remote memories require a finite 1536/4096-dimensional vector");
|
|
23274
|
+
const out = vector.slice(0, 1536);
|
|
23275
|
+
const norm = Math.sqrt(out.reduce((sum, v) => sum + v * v, 0));
|
|
23276
|
+
if (!norm) throw new Error("Remote query/content vector has no direction after MRL truncation");
|
|
23277
|
+
return out.map((v) => v / norm);
|
|
23278
|
+
}
|
|
23279
|
+
function sourceIds(value) {
|
|
23280
|
+
if (!value) return [];
|
|
23281
|
+
try {
|
|
23282
|
+
const parsed = JSON.parse(value);
|
|
23283
|
+
return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string") : [];
|
|
23284
|
+
} catch {
|
|
23285
|
+
return [];
|
|
23286
|
+
}
|
|
23287
|
+
}
|
|
23288
|
+
function stored(row) {
|
|
23289
|
+
return {
|
|
23290
|
+
uniqueId: row.memory_id,
|
|
23291
|
+
content: row.content,
|
|
23292
|
+
scope: row.scope,
|
|
23293
|
+
folderId: row.folder_id ?? null,
|
|
23294
|
+
userId: null,
|
|
23295
|
+
embedding: row.embedding ? JSON.stringify(row.embedding) : null,
|
|
23296
|
+
embeddingModel: row.embedding_model ?? null,
|
|
23297
|
+
sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
|
|
23298
|
+
proofCount: row.proof_count ?? null,
|
|
23299
|
+
source: row.source ?? null,
|
|
23300
|
+
media: parseMedia(row.media),
|
|
23301
|
+
eventTimeStart: row.event_time_start ?? null,
|
|
23302
|
+
eventTimeEnd: row.event_time_end ?? null,
|
|
23303
|
+
eventTimeKind: row.event_time_kind ?? null,
|
|
23304
|
+
topicsUserManaged: row.topics_user_managed ?? false,
|
|
23305
|
+
topics: parseTopics(row.topics),
|
|
23306
|
+
topicsUpdatedAt: row.topics_updated_at ?? null,
|
|
23307
|
+
topicsExtractedAt: row.topics_extracted_at ?? null,
|
|
23308
|
+
topicsExtractedVersion: row.topics_extracted_version ?? null,
|
|
23309
|
+
supersededBy: row.superseded_by ?? null,
|
|
23310
|
+
supersededAt: row.superseded_at ?? null,
|
|
23311
|
+
lastObservedAt: row.last_observed_at ?? null,
|
|
23312
|
+
factType: row.fact_type ?? null,
|
|
23313
|
+
archivedAt: row.archived_at ?? null,
|
|
23314
|
+
trustTier: row.trust_tier ?? null,
|
|
23315
|
+
visibility: row.visibility === "public" ? "public" : "private",
|
|
23316
|
+
twinOptIn: row.twin_opt_in ?? false,
|
|
23317
|
+
publishedAt: row.published_at ?? null,
|
|
23318
|
+
geohash: row.geohash ?? null,
|
|
23319
|
+
createdAt: new Date(row.created_at),
|
|
23320
|
+
updatedAt: new Date(row.updated_at),
|
|
23321
|
+
isDeleted: row.is_deleted
|
|
23322
|
+
};
|
|
23323
|
+
}
|
|
23324
|
+
function createRemoteMemoryPipeline(options) {
|
|
23325
|
+
const { persistence, embeddingOptions } = options;
|
|
23326
|
+
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
23327
|
+
const operation = (mode) => {
|
|
23328
|
+
const rejectUndecryptable = (failed) => {
|
|
23329
|
+
if (!failed.length) return;
|
|
23330
|
+
if (mode === "retain")
|
|
23331
|
+
throw new Error(
|
|
23332
|
+
`Remote memories could not decrypt ${failed.length} candidate row(s); refusing to retain until they are repaired`
|
|
23333
|
+
);
|
|
23334
|
+
getLogger().warn(
|
|
23335
|
+
`[memory/remote] Skipping ${failed.length} undecryptable candidate row(s)`,
|
|
23336
|
+
failed.map((failure) => failure.memory_id)
|
|
23337
|
+
);
|
|
23338
|
+
};
|
|
23339
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
23340
|
+
const remember = (items) => {
|
|
23341
|
+
items.forEach((item) => snapshots.set(item.memory.memory_id, item));
|
|
23342
|
+
return items.map((item) => stored(item.memory));
|
|
23343
|
+
};
|
|
23344
|
+
const get = async (id) => {
|
|
23345
|
+
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
23346
|
+
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
23347
|
+
snapshots.set(id, snapshot);
|
|
23348
|
+
return stored(snapshot.memory);
|
|
23349
|
+
};
|
|
23350
|
+
const prepare = async (query, search = {}) => {
|
|
23351
|
+
if (search.folderId !== void 0)
|
|
23352
|
+
throw new Error("Remote memories do not support folder filters");
|
|
23353
|
+
const facets = normalizeSubQueries(search.subQueries);
|
|
23354
|
+
const facetQueries = facets.length >= 2 ? facets : [];
|
|
23355
|
+
const start = Date.now();
|
|
23356
|
+
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
23357
|
+
const embed = (texts) => generateEmbeddings(texts, {
|
|
23358
|
+
...embeddingOptions,
|
|
23359
|
+
totalTimeoutMs: budgetMs
|
|
23360
|
+
});
|
|
23361
|
+
const embedFacets = async () => {
|
|
23362
|
+
if (!facetQueries.length) return [];
|
|
23363
|
+
try {
|
|
23364
|
+
const vectors2 = await embed(facetQueries);
|
|
23365
|
+
if (vectors2.length !== facetQueries.length)
|
|
23366
|
+
throw new Error("Incomplete facet embeddings");
|
|
23367
|
+
return vectors2.map(storedVector);
|
|
23368
|
+
} catch (error) {
|
|
23369
|
+
getLogger().warn(
|
|
23370
|
+
"[memory/remote] Facet embeddings unavailable; using primary query",
|
|
23371
|
+
error
|
|
23372
|
+
);
|
|
23373
|
+
return [];
|
|
23374
|
+
}
|
|
23375
|
+
};
|
|
23376
|
+
const [primary, facetEmbeddings] = await Promise.all([
|
|
23377
|
+
search.queryEmbedding ?? embed([query]).then((vectors2) => vectors2[0]),
|
|
23378
|
+
embedFacets()
|
|
23379
|
+
]);
|
|
23380
|
+
const queryEmbedding = storedVector(primary);
|
|
23381
|
+
const queryEmbedMs = Date.now() - start;
|
|
23382
|
+
const graph = search.entityRanking ?? [];
|
|
23383
|
+
const temporal = search.temporalRanking ?? [];
|
|
23384
|
+
const forced = /* @__PURE__ */ new Set();
|
|
23385
|
+
for (let i = 0; i < Math.max(graph.length, temporal.length) && forced.size < 100; i++) {
|
|
23386
|
+
if (graph[i] !== void 0) forced.add(graph[i]);
|
|
23387
|
+
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
23388
|
+
}
|
|
23389
|
+
const forceIds = [...forced];
|
|
23390
|
+
const windowOptions = (i, signal) => ({
|
|
23391
|
+
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
23392
|
+
force_ids: i === 0 ? forceIds : [],
|
|
23393
|
+
...search.scopes && { scopes: search.scopes },
|
|
23394
|
+
...search.factTypes && { fact_types: search.factTypes },
|
|
23395
|
+
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
23396
|
+
include_archived: search.includeArchived,
|
|
23397
|
+
embedding_model: model,
|
|
23398
|
+
...signal && { signal }
|
|
23399
|
+
});
|
|
23400
|
+
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
23401
|
+
let windows;
|
|
23402
|
+
if (mode === "retain") {
|
|
23403
|
+
windows = await Promise.all(
|
|
23404
|
+
vectors.map((embedding, i) => persistence.candidateSet(embedding, windowOptions(i)))
|
|
23405
|
+
);
|
|
23406
|
+
} else {
|
|
23407
|
+
const deadline = new AbortController();
|
|
23408
|
+
const timer = setTimeout(
|
|
23409
|
+
() => deadline.abort(
|
|
23410
|
+
new RemoteMemoryError("Remote recall exceeded its query budget", 408, "timeout")
|
|
23411
|
+
),
|
|
23412
|
+
Math.max(0, start + budgetMs - Date.now())
|
|
23413
|
+
);
|
|
23414
|
+
try {
|
|
23415
|
+
windows = await Promise.all(
|
|
23416
|
+
vectors.map(
|
|
23417
|
+
(embedding, i) => persistence.candidates(embedding, windowOptions(i, deadline.signal))
|
|
23418
|
+
)
|
|
23419
|
+
);
|
|
23420
|
+
} finally {
|
|
23421
|
+
clearTimeout(timer);
|
|
23422
|
+
}
|
|
23423
|
+
}
|
|
23424
|
+
rejectUndecryptable([
|
|
23425
|
+
...new Map(
|
|
23426
|
+
windows.flatMap((window2) => window2.failed).map((failure) => [failure.memory_id, failure])
|
|
23427
|
+
).values()
|
|
23428
|
+
]);
|
|
23429
|
+
const items = [
|
|
23430
|
+
...new Map(
|
|
23431
|
+
windows.flatMap((window2) => window2.items).map((item) => [item.memory.memory_id, item])
|
|
23432
|
+
).values()
|
|
23433
|
+
];
|
|
23434
|
+
const memories = remember(items);
|
|
23435
|
+
return {
|
|
23436
|
+
memories,
|
|
23437
|
+
embeddedItems: memories.map((memory) => ({
|
|
23438
|
+
id: memory.uniqueId,
|
|
23439
|
+
content: memory.content,
|
|
23440
|
+
embedding: JSON.parse(memory.embedding ?? "[]"),
|
|
23441
|
+
createdAt: memory.createdAt,
|
|
23442
|
+
updatedAt: memory.updatedAt,
|
|
23443
|
+
proofCount: memory.proofCount,
|
|
23444
|
+
lastObservedAt: memory.lastObservedAt,
|
|
23445
|
+
eventTimeStart: memory.eventTimeStart,
|
|
23446
|
+
eventTimeEnd: memory.eventTimeEnd,
|
|
23447
|
+
eventTimeKind: memory.eventTimeKind === "point" || memory.eventTimeKind === "range" || memory.eventTimeKind === "ongoing" ? memory.eventTimeKind : null,
|
|
23448
|
+
factType: memory.factType,
|
|
23449
|
+
sourceChunkIds: memory.sourceChunkIds
|
|
23450
|
+
})),
|
|
23451
|
+
queryEmbedding,
|
|
23452
|
+
facetEmbeddings,
|
|
23453
|
+
vaultSize: Math.max(windows[0].total_count ?? 0, items.length),
|
|
23454
|
+
embeddingFailure: windows.some((window2) => (window2.unavailable_count ?? 0) > 0),
|
|
23455
|
+
embeddingsUnavailable: (windows[0].total_count ?? items.length) > 0 && !memories.some((memory) => memory.embedding),
|
|
23456
|
+
decryptLast: true,
|
|
23457
|
+
rowsDecrypted: items.length,
|
|
23458
|
+
queryEmbedMs,
|
|
23459
|
+
rowsEmbedded: 0
|
|
23460
|
+
};
|
|
23461
|
+
};
|
|
23462
|
+
const createRow = (input) => {
|
|
23463
|
+
if (input.folderId !== void 0 && input.folderId !== null)
|
|
23464
|
+
throw new Error("Remote memories do not support folders");
|
|
23465
|
+
const now = Date.now();
|
|
23466
|
+
return {
|
|
23467
|
+
memory_id: (0, import_uuid5.v7)(),
|
|
23468
|
+
content: input.content,
|
|
23469
|
+
scope: input.scope ?? "private",
|
|
23470
|
+
created_at: now,
|
|
23471
|
+
updated_at: now,
|
|
23472
|
+
is_deleted: false,
|
|
23473
|
+
...input.embedding !== void 0 && {
|
|
23474
|
+
embedding: storedVector(JSON.parse(input.embedding)),
|
|
23475
|
+
embedding_model: input.embeddingModel
|
|
23476
|
+
},
|
|
23477
|
+
source_chunk_ids: JSON.stringify(input.sourceChunkIds ?? []),
|
|
23478
|
+
proof_count: input.proofCount ?? 1,
|
|
23479
|
+
source: input.source ?? "manual",
|
|
23480
|
+
...input.eventTime && {
|
|
23481
|
+
event_time_start: input.eventTime.start ?? void 0,
|
|
23482
|
+
event_time_end: input.eventTime.end ?? void 0,
|
|
23483
|
+
event_time_kind: input.eventTime.kind ?? void 0
|
|
23484
|
+
},
|
|
23485
|
+
fact_type: input.factType,
|
|
23486
|
+
trust_tier: normalizeTrustTier(input.trustTier) ?? void 0,
|
|
23487
|
+
geohash: input.geohash,
|
|
23488
|
+
visibility: "private",
|
|
23489
|
+
twin_opt_in: false
|
|
23490
|
+
};
|
|
23491
|
+
};
|
|
23492
|
+
const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
|
|
23493
|
+
const port = {
|
|
23494
|
+
prepare,
|
|
23495
|
+
get,
|
|
23496
|
+
getFresh: async (id) => {
|
|
23497
|
+
const current = await persistence.get(id);
|
|
23498
|
+
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
23499
|
+
},
|
|
23500
|
+
tombstones: async (embedding, embeddingModel, scope, folderId) => {
|
|
23501
|
+
if (folderId !== void 0) throw new Error("Remote memories do not support folders");
|
|
23502
|
+
const window2 = await persistence.candidateSet(storedVector(embedding), {
|
|
23503
|
+
limit: 1,
|
|
23504
|
+
scopes: [scope],
|
|
23505
|
+
embedding_model: embeddingModel,
|
|
23506
|
+
strict_model: true,
|
|
23507
|
+
include_deleted: true,
|
|
23508
|
+
deleted_only: true
|
|
23509
|
+
});
|
|
23510
|
+
rejectUndecryptable(window2.failed);
|
|
23511
|
+
return remember(window2.items);
|
|
23512
|
+
},
|
|
23513
|
+
create: (input) => write(createRow(input), 0),
|
|
23514
|
+
update: async (id, patch) => {
|
|
23515
|
+
const existing = await get(id);
|
|
23516
|
+
if (!existing) return null;
|
|
23517
|
+
const snapshot = snapshots.get(id);
|
|
23518
|
+
const memory = {
|
|
23519
|
+
...snapshot.memory,
|
|
23520
|
+
content: patch.content,
|
|
23521
|
+
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
|
|
23522
|
+
};
|
|
23523
|
+
if (patch.scope !== void 0) memory.scope = patch.scope;
|
|
23524
|
+
if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
|
|
23525
|
+
delete memory.embedding;
|
|
23526
|
+
delete memory.embedding_model;
|
|
23527
|
+
}
|
|
23528
|
+
if (patch.embedding !== void 0) {
|
|
23529
|
+
memory.embedding = patch.embedding === null ? [] : storedVector(JSON.parse(patch.embedding));
|
|
23530
|
+
memory.embedding_model = patch.embeddingModel ?? void 0;
|
|
23531
|
+
}
|
|
23532
|
+
const observed = sourceIds(memory.source_chunk_ids);
|
|
23533
|
+
const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
|
|
23534
|
+
if (patch.sourceChunkIds !== void 0)
|
|
23535
|
+
memory.source_chunk_ids = JSON.stringify(
|
|
23536
|
+
patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
|
|
23537
|
+
);
|
|
23538
|
+
if (!replay) {
|
|
23539
|
+
if (patch.proofCountIncrement !== void 0)
|
|
23540
|
+
memory.proof_count = (memory.proof_count ?? 1) + patch.proofCountIncrement;
|
|
23541
|
+
else if (patch.proofCount !== void 0) memory.proof_count = patch.proofCount;
|
|
23542
|
+
if (patch.lastObservedAt !== void 0) memory.last_observed_at = patch.lastObservedAt;
|
|
23543
|
+
}
|
|
23544
|
+
if (patch.source !== void 0) memory.source = patch.source;
|
|
23545
|
+
if (patch.factType !== void 0) memory.fact_type = patch.factType;
|
|
23546
|
+
if (patch.trustTier !== void 0)
|
|
23547
|
+
memory.trust_tier = normalizeTrustTier(patch.trustTier) ?? void 0;
|
|
23548
|
+
if (patch.topicsUserManaged !== void 0)
|
|
23549
|
+
memory.topics_user_managed = patch.topicsUserManaged;
|
|
23550
|
+
if (patch.eventTime !== void 0) {
|
|
23551
|
+
memory.event_time_start = patch.eventTime.start ?? void 0;
|
|
23552
|
+
memory.event_time_end = patch.eventTime.end ?? void 0;
|
|
23553
|
+
memory.event_time_kind = patch.eventTime.kind ?? void 0;
|
|
23554
|
+
}
|
|
23555
|
+
if (patch.restore) memory.archived_at = void 0;
|
|
23556
|
+
return write(memory, snapshot);
|
|
23557
|
+
},
|
|
23558
|
+
supersede: async (id, successor) => {
|
|
23559
|
+
const [target, newer] = await Promise.all([get(id), get(successor)]);
|
|
23560
|
+
if (!target || !newer || id === successor) return false;
|
|
23561
|
+
const old = snapshots.get(id);
|
|
23562
|
+
const next = snapshots.get(successor);
|
|
23563
|
+
remember(
|
|
23564
|
+
await persistence.putMany([
|
|
23565
|
+
{
|
|
23566
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
23567
|
+
expectedVersion: old
|
|
23568
|
+
},
|
|
23569
|
+
{ memory: next.memory, expectedVersion: next }
|
|
23570
|
+
])
|
|
23571
|
+
);
|
|
23572
|
+
return true;
|
|
23573
|
+
},
|
|
23574
|
+
createSuperseding: async (input, targetId) => {
|
|
23575
|
+
const target = await get(targetId);
|
|
23576
|
+
if (!target) return { created: null, retired: false };
|
|
23577
|
+
const snapshot = snapshots.get(targetId);
|
|
23578
|
+
const successor = createRow(input);
|
|
23579
|
+
const rows = remember(
|
|
23580
|
+
await persistence.putMany([
|
|
23581
|
+
{ memory: successor, expectedVersion: 0 },
|
|
23582
|
+
{
|
|
23583
|
+
memory: {
|
|
23584
|
+
...snapshot.memory,
|
|
23585
|
+
superseded_by: successor.memory_id,
|
|
23586
|
+
superseded_at: Date.now()
|
|
23587
|
+
},
|
|
23588
|
+
expectedVersion: snapshot
|
|
23589
|
+
}
|
|
23590
|
+
])
|
|
23591
|
+
);
|
|
23592
|
+
return { created: rows[0], retired: true };
|
|
23593
|
+
}
|
|
23594
|
+
};
|
|
23595
|
+
return { prepare, port };
|
|
23596
|
+
};
|
|
23597
|
+
return {
|
|
23598
|
+
recall: async (query, recallOptions = {}) => {
|
|
23599
|
+
const { prepare } = operation("recall");
|
|
23600
|
+
return recall(
|
|
23601
|
+
query,
|
|
23602
|
+
{
|
|
23603
|
+
embeddingOptions,
|
|
23604
|
+
factSource: {
|
|
23605
|
+
graphRanking: options.graphRanking,
|
|
23606
|
+
temporalRanking: options.temporalRanking,
|
|
23607
|
+
search: async (text12, searchOptions) => {
|
|
23608
|
+
const prepared = await prepare(text12, searchOptions);
|
|
23609
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
23610
|
+
text12,
|
|
23611
|
+
prepared,
|
|
23612
|
+
embeddingOptions,
|
|
23613
|
+
searchOptions
|
|
23614
|
+
);
|
|
23615
|
+
return {
|
|
23616
|
+
...ranked,
|
|
23617
|
+
rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
|
|
23618
|
+
decryptLast: true,
|
|
23619
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
23620
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
23621
|
+
rowsEmbedded: 0
|
|
23622
|
+
};
|
|
23623
|
+
}
|
|
23624
|
+
}
|
|
23625
|
+
},
|
|
23626
|
+
{ ...recallOptions, types: ["fact"] }
|
|
23627
|
+
);
|
|
23628
|
+
},
|
|
23629
|
+
retain: async (content, retainOptions) => {
|
|
23630
|
+
const { port } = operation("retain");
|
|
23631
|
+
return retainWithPersistence(
|
|
23632
|
+
content,
|
|
23633
|
+
{
|
|
23634
|
+
persistence: port,
|
|
23635
|
+
embeddingOptions,
|
|
23636
|
+
vaultCache: /* @__PURE__ */ new Map(),
|
|
23637
|
+
normalizeEmbedding: storedVector
|
|
23638
|
+
},
|
|
23639
|
+
retainOptions
|
|
23640
|
+
);
|
|
23641
|
+
}
|
|
23642
|
+
};
|
|
23643
|
+
}
|
|
23644
|
+
|
|
22842
23645
|
// src/lib/memory/synthesizeProfile.ts
|
|
22843
23646
|
init_internalFlowMarker();
|
|
22844
23647
|
init_logger();
|
|
@@ -29098,7 +29901,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
29098
29901
|
const recordName = `backup_${filename.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
29099
29902
|
const arrayBuffer = await content.arrayBuffer();
|
|
29100
29903
|
const base64Data = uint8ArrayToBase64(new Uint8Array(arrayBuffer));
|
|
29101
|
-
const
|
|
29904
|
+
const record2 = {
|
|
29102
29905
|
recordType: RECORD_TYPE,
|
|
29103
29906
|
recordName,
|
|
29104
29907
|
fields: {
|
|
@@ -29108,7 +29911,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
29108
29911
|
contentType: { value: content.type || "application/json" }
|
|
29109
29912
|
}
|
|
29110
29913
|
};
|
|
29111
|
-
const response = await database.saveRecords(
|
|
29914
|
+
const response = await database.saveRecords(record2);
|
|
29112
29915
|
if (!response.records || response.records.length === 0) {
|
|
29113
29916
|
throw new Error("Failed to upload file to iCloud");
|
|
29114
29917
|
}
|
|
@@ -29134,11 +29937,11 @@ async function listICloudFiles() {
|
|
|
29134
29937
|
while (response.continuationMarker) {
|
|
29135
29938
|
break;
|
|
29136
29939
|
}
|
|
29137
|
-
const files = allRecords.map((
|
|
29138
|
-
recordName:
|
|
29139
|
-
filename:
|
|
29140
|
-
modifiedAt: new Date(
|
|
29141
|
-
size: typeof
|
|
29940
|
+
const files = allRecords.map((record2) => ({
|
|
29941
|
+
recordName: record2.recordName,
|
|
29942
|
+
filename: record2.fields.filename?.value ?? "",
|
|
29943
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
29944
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
29142
29945
|
}));
|
|
29143
29946
|
return files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
29144
29947
|
}
|
|
@@ -29151,8 +29954,8 @@ async function downloadICloudFile(recordName) {
|
|
|
29151
29954
|
if (!response.records || response.records.length === 0) {
|
|
29152
29955
|
throw new Error(`File not found: ${recordName}`);
|
|
29153
29956
|
}
|
|
29154
|
-
const
|
|
29155
|
-
const dataField =
|
|
29957
|
+
const record2 = response.records[0];
|
|
29958
|
+
const dataField = record2.fields.data?.value;
|
|
29156
29959
|
if (!dataField) {
|
|
29157
29960
|
throw new Error("No data in record");
|
|
29158
29961
|
}
|
|
@@ -29186,12 +29989,12 @@ async function findICloudFile(filename) {
|
|
|
29186
29989
|
if (!response.records || response.records.length === 0) {
|
|
29187
29990
|
return null;
|
|
29188
29991
|
}
|
|
29189
|
-
const
|
|
29992
|
+
const record2 = response.records[0];
|
|
29190
29993
|
return {
|
|
29191
|
-
recordName:
|
|
29192
|
-
filename:
|
|
29193
|
-
modifiedAt: new Date(
|
|
29194
|
-
size: typeof
|
|
29994
|
+
recordName: record2.recordName,
|
|
29995
|
+
filename: record2.fields.filename?.value ?? "",
|
|
29996
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
29997
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
29195
29998
|
};
|
|
29196
29999
|
}
|
|
29197
30000
|
|
|
@@ -29346,8 +30149,8 @@ async function getStoredTokenData5(provider, walletAddress) {
|
|
|
29346
30149
|
return null;
|
|
29347
30150
|
}
|
|
29348
30151
|
}
|
|
29349
|
-
async function readTokenRow(
|
|
29350
|
-
if (
|
|
30152
|
+
async function readTokenRow(stored2, provider, walletAddress) {
|
|
30153
|
+
if (stored2.startsWith(ENCRYPTED_PREFIX6)) {
|
|
29351
30154
|
if (!walletAddress) {
|
|
29352
30155
|
getLogger().warn(
|
|
29353
30156
|
`Encrypted OAuth token found for ${provider} but no wallet address provided`
|
|
@@ -29355,7 +30158,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
29355
30158
|
return null;
|
|
29356
30159
|
}
|
|
29357
30160
|
try {
|
|
29358
|
-
const encryptedData =
|
|
30161
|
+
const encryptedData = stored2.slice(ENCRYPTED_PREFIX6.length);
|
|
29359
30162
|
let decryptedJson;
|
|
29360
30163
|
try {
|
|
29361
30164
|
decryptedJson = await decryptData(encryptedData, walletAddress);
|
|
@@ -29370,7 +30173,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
29370
30173
|
return null;
|
|
29371
30174
|
}
|
|
29372
30175
|
}
|
|
29373
|
-
return parsePlaintextToken(
|
|
30176
|
+
return parsePlaintextToken(stored2, walletAddress);
|
|
29374
30177
|
}
|
|
29375
30178
|
async function storeTokenData5(provider, data, walletAddress) {
|
|
29376
30179
|
if (typeof window === "undefined") return;
|
|
@@ -29446,8 +30249,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
29446
30249
|
const keys = [scopedKey, legacyKey];
|
|
29447
30250
|
const isEncrypted2 = (value) => !!value && value.startsWith(ENCRYPTED_PREFIX6);
|
|
29448
30251
|
const plaintextAt = (key) => {
|
|
29449
|
-
const
|
|
29450
|
-
return
|
|
30252
|
+
const stored2 = sessionStorage.getItem(key) ?? localStorage.getItem(key);
|
|
30253
|
+
return stored2 && !isEncrypted2(stored2) ? stored2 : null;
|
|
29451
30254
|
};
|
|
29452
30255
|
let tokenToMigrate = null;
|
|
29453
30256
|
for (const key of keys) {
|
|
@@ -29459,8 +30262,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
29459
30262
|
}
|
|
29460
30263
|
if (!tokenToMigrate) {
|
|
29461
30264
|
for (const key of keys) {
|
|
29462
|
-
const
|
|
29463
|
-
if (isEncrypted2(localStorage.getItem(key)) &&
|
|
30265
|
+
const stored2 = sessionStorage.getItem(key);
|
|
30266
|
+
if (isEncrypted2(localStorage.getItem(key)) && stored2 && !isEncrypted2(stored2)) {
|
|
29464
30267
|
sessionStorage.removeItem(key);
|
|
29465
30268
|
}
|
|
29466
30269
|
}
|
|
@@ -29516,17 +30319,17 @@ function storeOAuthState2(state) {
|
|
|
29516
30319
|
}
|
|
29517
30320
|
function getAndClearOAuthState4() {
|
|
29518
30321
|
if (typeof window === "undefined") return null;
|
|
29519
|
-
const
|
|
30322
|
+
const stored2 = sessionStorage.getItem(STATE_STORAGE_KEY);
|
|
29520
30323
|
sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
29521
|
-
if (!
|
|
30324
|
+
if (!stored2) return null;
|
|
29522
30325
|
try {
|
|
29523
|
-
const parsed = JSON.parse(
|
|
30326
|
+
const parsed = JSON.parse(stored2);
|
|
29524
30327
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
29525
30328
|
return parsed.state;
|
|
29526
30329
|
}
|
|
29527
30330
|
} catch {
|
|
29528
30331
|
}
|
|
29529
|
-
return
|
|
30332
|
+
return stored2;
|
|
29530
30333
|
}
|
|
29531
30334
|
function isDropboxCallback() {
|
|
29532
30335
|
if (typeof window === "undefined") return false;
|
|
@@ -29710,17 +30513,17 @@ function storeOAuthState3(state) {
|
|
|
29710
30513
|
}
|
|
29711
30514
|
function getAndClearOAuthState5() {
|
|
29712
30515
|
if (typeof window === "undefined") return null;
|
|
29713
|
-
const
|
|
30516
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY4);
|
|
29714
30517
|
sessionStorage.removeItem(CODE_STORAGE_KEY4);
|
|
29715
|
-
if (!
|
|
30518
|
+
if (!stored2) return null;
|
|
29716
30519
|
try {
|
|
29717
|
-
const parsed = JSON.parse(
|
|
30520
|
+
const parsed = JSON.parse(stored2);
|
|
29718
30521
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
29719
30522
|
return parsed.state;
|
|
29720
30523
|
}
|
|
29721
30524
|
} catch {
|
|
29722
30525
|
}
|
|
29723
|
-
return
|
|
30526
|
+
return stored2;
|
|
29724
30527
|
}
|
|
29725
30528
|
function isGoogleDriveCallback() {
|
|
29726
30529
|
if (typeof window === "undefined") return false;
|
|
@@ -31664,18 +32467,18 @@ async function blobToDataUri(blob) {
|
|
|
31664
32467
|
reader.readAsDataURL(blob);
|
|
31665
32468
|
});
|
|
31666
32469
|
}
|
|
31667
|
-
async function storedToLlmapiMessage(
|
|
31668
|
-
let textContent =
|
|
32470
|
+
async function storedToLlmapiMessage(stored2, encryptionKey, resolveMediaByIds) {
|
|
32471
|
+
let textContent = stored2.content;
|
|
31669
32472
|
const fileUrlMap = /* @__PURE__ */ new Map();
|
|
31670
32473
|
const imageParts = [];
|
|
31671
|
-
if (
|
|
31672
|
-
for (const file of
|
|
32474
|
+
if (stored2.role !== "assistant" && stored2.files?.length) {
|
|
32475
|
+
for (const file of stored2.files) {
|
|
31673
32476
|
if (isSendableImageURL(file.url)) {
|
|
31674
32477
|
imageParts.push({
|
|
31675
32478
|
type: "image_url",
|
|
31676
32479
|
image_url: { url: file.url }
|
|
31677
32480
|
});
|
|
31678
|
-
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl,
|
|
32481
|
+
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
31679
32482
|
imageParts.push({
|
|
31680
32483
|
type: "image_url",
|
|
31681
32484
|
image_url: { url: file.sourceUrl }
|
|
@@ -31695,11 +32498,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31695
32498
|
}
|
|
31696
32499
|
}
|
|
31697
32500
|
}
|
|
31698
|
-
} else if (
|
|
32501
|
+
} else if (stored2.role === "assistant" && stored2.files?.length) {
|
|
31699
32502
|
const expiredFileIds = [];
|
|
31700
|
-
for (const file of
|
|
32503
|
+
for (const file of stored2.files) {
|
|
31701
32504
|
if (file.sourceUrl) {
|
|
31702
|
-
if (!isR2UrlExpired(file.sourceUrl,
|
|
32505
|
+
if (!isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
31703
32506
|
fileUrlMap.set(file.id, file.sourceUrl);
|
|
31704
32507
|
} else {
|
|
31705
32508
|
expiredFileIds.push(file.id);
|
|
@@ -31712,11 +32515,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31712
32515
|
[${expiredFileIds.length} expired image URL${expiredFileIds.length > 1 ? "s" : ""} omitted \u2014 the user can still see ${expiredFileIds.length > 1 ? "them" : "it"} locally]`;
|
|
31713
32516
|
}
|
|
31714
32517
|
}
|
|
31715
|
-
if (
|
|
32518
|
+
if (stored2.fileIds?.length && resolveMediaByIds) {
|
|
31716
32519
|
try {
|
|
31717
|
-
const mediaItems = await resolveMediaByIds(
|
|
32520
|
+
const mediaItems = await resolveMediaByIds(stored2.fileIds);
|
|
31718
32521
|
for (const media of mediaItems) {
|
|
31719
|
-
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl,
|
|
32522
|
+
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl, stored2.createdAt)) {
|
|
31720
32523
|
fileUrlMap.set(media.mediaId, media.sourceUrl);
|
|
31721
32524
|
}
|
|
31722
32525
|
}
|
|
@@ -31740,7 +32543,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31740
32543
|
return "";
|
|
31741
32544
|
}
|
|
31742
32545
|
);
|
|
31743
|
-
if (
|
|
32546
|
+
if (stored2.role === "assistant" && fileUrlMap.size > 0) {
|
|
31744
32547
|
const unreferencedImages = [...fileUrlMap.entries()].filter(
|
|
31745
32548
|
([, url]) => !textContent.includes(url)
|
|
31746
32549
|
);
|
|
@@ -31752,11 +32555,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31752
32555
|
textContent = textContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
31753
32556
|
const content = [{ type: "text", text: textContent }, ...imageParts];
|
|
31754
32557
|
const messages = [];
|
|
31755
|
-
if (
|
|
32558
|
+
if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
|
|
31756
32559
|
messages.push({
|
|
31757
|
-
role:
|
|
32560
|
+
role: stored2.role,
|
|
31758
32561
|
content: void 0,
|
|
31759
|
-
tool_calls:
|
|
32562
|
+
tool_calls: stored2.toolCallEvents.map((event) => ({
|
|
31760
32563
|
id: event.id,
|
|
31761
32564
|
type: "function",
|
|
31762
32565
|
function: {
|
|
@@ -31765,7 +32568,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31765
32568
|
}
|
|
31766
32569
|
}))
|
|
31767
32570
|
});
|
|
31768
|
-
for (const event of
|
|
32571
|
+
for (const event of stored2.toolCallEvents) {
|
|
31769
32572
|
if (event.id && event.output !== void 0 && event.output !== null) {
|
|
31770
32573
|
messages.push({
|
|
31771
32574
|
role: "tool",
|
|
@@ -31776,12 +32579,12 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31776
32579
|
}
|
|
31777
32580
|
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();
|
|
31778
32581
|
messages.push({
|
|
31779
|
-
role:
|
|
32582
|
+
role: stored2.role,
|
|
31780
32583
|
content: [{ type: "text", text: postToolText }]
|
|
31781
32584
|
});
|
|
31782
32585
|
} else {
|
|
31783
32586
|
messages.push({
|
|
31784
|
-
role:
|
|
32587
|
+
role: stored2.role,
|
|
31785
32588
|
content
|
|
31786
32589
|
});
|
|
31787
32590
|
}
|
|
@@ -35600,19 +36403,19 @@ function startObserve(entry, walletAddress) {
|
|
|
35600
36403
|
"updated_at"
|
|
35601
36404
|
]).subscribe({
|
|
35602
36405
|
next: (records) => {
|
|
35603
|
-
const
|
|
35604
|
-
if (!
|
|
36406
|
+
const record2 = records[0];
|
|
36407
|
+
if (!record2) return;
|
|
35605
36408
|
const patch = {
|
|
35606
36409
|
userPreference: {
|
|
35607
|
-
uniqueId:
|
|
35608
|
-
walletAddress:
|
|
35609
|
-
nickname:
|
|
35610
|
-
occupation:
|
|
35611
|
-
description:
|
|
35612
|
-
models:
|
|
35613
|
-
personality:
|
|
35614
|
-
createdAt:
|
|
35615
|
-
updatedAt:
|
|
36410
|
+
uniqueId: record2.id,
|
|
36411
|
+
walletAddress: record2.walletAddress,
|
|
36412
|
+
nickname: record2.nickname,
|
|
36413
|
+
occupation: record2.occupation,
|
|
36414
|
+
description: record2.description,
|
|
36415
|
+
models: record2.models,
|
|
36416
|
+
personality: record2.personality,
|
|
36417
|
+
createdAt: record2.createdAt,
|
|
36418
|
+
updatedAt: record2.updatedAt
|
|
35616
36419
|
}
|
|
35617
36420
|
};
|
|
35618
36421
|
if (isInitialEmission) {
|
|
@@ -36831,6 +37634,7 @@ function useWalletBinding(options = {}) {
|
|
|
36831
37634
|
R2_DEFAULT_TTL_MS,
|
|
36832
37635
|
RECALL_MAX_LIMIT,
|
|
36833
37636
|
RECALL_TOOL_NAME,
|
|
37637
|
+
RemoteMemoryError,
|
|
36834
37638
|
RerankerUnavailableError,
|
|
36835
37639
|
SDK_SCHEMA_VERSION,
|
|
36836
37640
|
SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -36922,6 +37726,8 @@ function useWalletBinding(options = {}) {
|
|
|
36922
37726
|
createPlatformCursorStore,
|
|
36923
37727
|
createProjectOp,
|
|
36924
37728
|
createRecallTool,
|
|
37729
|
+
createRemoteMemoryPersistence,
|
|
37730
|
+
createRemoteMemoryPipeline,
|
|
36925
37731
|
createSavedToolOp,
|
|
36926
37732
|
createServerToolsFilter,
|
|
36927
37733
|
createStockPricePreProcessor,
|