@anuma/sdk 6.33.2 → 6.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +1304 -300
- package/dist/expo/index.d.mts +278 -11
- package/dist/expo/index.d.ts +278 -11
- package/dist/expo/index.mjs +1297 -300
- package/dist/index.cjs +18 -6
- package/dist/index.mjs +18 -6
- package/dist/memory/context.d.mts +21 -1
- package/dist/memory/context.d.ts +21 -1
- package/dist/react/index.cjs +1385 -381
- package/dist/react/index.d.mts +311 -11
- package/dist/react/index.d.ts +311 -11
- package/dist/react/index.mjs +1378 -381
- package/dist/server/index.cjs +319 -99
- package/dist/server/index.d.mts +138 -11
- package/dist/server/index.d.ts +138 -11
- package/dist/server/index.mjs +316 -99
- package/dist/telemetry/index.d.mts +3 -4
- package/dist/telemetry/index.d.ts +3 -4
- package/dist/tools/selection/index.cjs +18 -6
- package/dist/tools/selection/index.mjs +18 -6
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -1424,7 +1424,10 @@ __export(index_exports, {
|
|
|
1424
1424
|
LoggerProvider: () => LoggerProvider,
|
|
1425
1425
|
MAX_HOPS: () => MAX_HOPS,
|
|
1426
1426
|
MEDIUM_TTL_MS: () => MEDIUM_TTL_MS,
|
|
1427
|
+
MEMORY_KINDS: () => MEMORY_KINDS,
|
|
1428
|
+
MEMORY_LEVELS: () => MEMORY_LEVELS,
|
|
1427
1429
|
MemoryEntityModel: () => MemoryEntity,
|
|
1430
|
+
MemoryLevelError: () => MemoryLevelError,
|
|
1428
1431
|
NEVER_TTL_MS: () => NEVER_TTL_MS,
|
|
1429
1432
|
NODE_BUDGET: () => NODE_BUDGET,
|
|
1430
1433
|
PAST_EVENT_GRACE_MS: () => PAST_EVENT_GRACE_MS,
|
|
@@ -1437,6 +1440,7 @@ __export(index_exports, {
|
|
|
1437
1440
|
R2_DEFAULT_TTL_MS: () => R2_DEFAULT_TTL_MS,
|
|
1438
1441
|
RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
|
|
1439
1442
|
RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
|
|
1443
|
+
RemoteMemoryError: () => RemoteMemoryError,
|
|
1440
1444
|
RerankerUnavailableError: () => RerankerUnavailableError,
|
|
1441
1445
|
SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
|
|
1442
1446
|
SERVER_TOOL_DEPENDENCY_SETS: () => SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -1528,6 +1532,8 @@ __export(index_exports, {
|
|
|
1528
1532
|
createPlatformCursorStore: () => createPlatformCursorStore,
|
|
1529
1533
|
createProjectOp: () => createProjectOp,
|
|
1530
1534
|
createRecallTool: () => createRecallTool,
|
|
1535
|
+
createRemoteMemoryPersistence: () => createRemoteMemoryPersistence,
|
|
1536
|
+
createRemoteMemoryPipeline: () => createRemoteMemoryPipeline,
|
|
1531
1537
|
createSavedToolOp: () => createSavedToolOp,
|
|
1532
1538
|
createServerToolsFilter: () => createServerToolsFilter,
|
|
1533
1539
|
createStockPricePreProcessor: () => createStockPricePreProcessor,
|
|
@@ -3554,10 +3560,10 @@ function parsePlaintextToken(raw, walletAddress) {
|
|
|
3554
3560
|
return null;
|
|
3555
3561
|
}
|
|
3556
3562
|
if (!parsed || typeof parsed !== "object") return null;
|
|
3557
|
-
const
|
|
3558
|
-
const data =
|
|
3563
|
+
const record2 = parsed;
|
|
3564
|
+
const data = record2.token?.accessToken ? record2.token : record2;
|
|
3559
3565
|
if (!data?.accessToken) return null;
|
|
3560
|
-
if (
|
|
3566
|
+
if (record2.wallet && record2.wallet !== walletAddress) return null;
|
|
3561
3567
|
return data;
|
|
3562
3568
|
}
|
|
3563
3569
|
function promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress) {
|
|
@@ -3681,8 +3687,8 @@ async function storeTokenData(data, walletAddress) {
|
|
|
3681
3687
|
getLogger().warn("Failed to encrypt GitHub OAuth token:", error);
|
|
3682
3688
|
}
|
|
3683
3689
|
}
|
|
3684
|
-
const
|
|
3685
|
-
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(
|
|
3690
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
3691
|
+
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(record2));
|
|
3686
3692
|
}
|
|
3687
3693
|
function clearGithubToken(walletAddress) {
|
|
3688
3694
|
if (typeof window === "undefined") return;
|
|
@@ -3731,17 +3737,17 @@ function storeOAuthState(state) {
|
|
|
3731
3737
|
}
|
|
3732
3738
|
function getAndClearOAuthState() {
|
|
3733
3739
|
if (typeof window === "undefined") return null;
|
|
3734
|
-
const
|
|
3740
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY);
|
|
3735
3741
|
sessionStorage.removeItem(CODE_STORAGE_KEY);
|
|
3736
|
-
if (!
|
|
3742
|
+
if (!stored2) return null;
|
|
3737
3743
|
try {
|
|
3738
|
-
const parsed = JSON.parse(
|
|
3744
|
+
const parsed = JSON.parse(stored2);
|
|
3739
3745
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
3740
3746
|
return parsed.state;
|
|
3741
3747
|
}
|
|
3742
3748
|
} catch {
|
|
3743
3749
|
}
|
|
3744
|
-
return
|
|
3750
|
+
return stored2;
|
|
3745
3751
|
}
|
|
3746
3752
|
function isGithubCallback(callbackPath) {
|
|
3747
3753
|
if (typeof window === "undefined") return false;
|
|
@@ -4034,8 +4040,8 @@ async function storeTokenData2(data, walletAddress) {
|
|
|
4034
4040
|
getLogger().warn("Failed to encrypt Calendar OAuth token:", error);
|
|
4035
4041
|
}
|
|
4036
4042
|
}
|
|
4037
|
-
const
|
|
4038
|
-
sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(
|
|
4043
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
4044
|
+
sessionStorage.setItem(getTokenStorageKey2(walletAddress), JSON.stringify(record2));
|
|
4039
4045
|
}
|
|
4040
4046
|
function clearCalendarToken(walletAddress) {
|
|
4041
4047
|
if (typeof window === "undefined") return;
|
|
@@ -4075,17 +4081,17 @@ function getRedirectUri2(callbackPath) {
|
|
|
4075
4081
|
}
|
|
4076
4082
|
function getAndClearOAuthState2() {
|
|
4077
4083
|
if (typeof window === "undefined") return null;
|
|
4078
|
-
const
|
|
4084
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY2);
|
|
4079
4085
|
sessionStorage.removeItem(CODE_STORAGE_KEY2);
|
|
4080
|
-
if (!
|
|
4086
|
+
if (!stored2) return null;
|
|
4081
4087
|
try {
|
|
4082
|
-
const parsed = JSON.parse(
|
|
4088
|
+
const parsed = JSON.parse(stored2);
|
|
4083
4089
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
4084
4090
|
return parsed.state;
|
|
4085
4091
|
}
|
|
4086
4092
|
} catch {
|
|
4087
4093
|
}
|
|
4088
|
-
return
|
|
4094
|
+
return stored2;
|
|
4089
4095
|
}
|
|
4090
4096
|
function isCalendarCallback(callbackPath) {
|
|
4091
4097
|
if (typeof window === "undefined") return false;
|
|
@@ -4360,8 +4366,8 @@ async function storeTokenData3(data, walletAddress) {
|
|
|
4360
4366
|
getLogger().warn("Failed to encrypt Drive OAuth token:", error);
|
|
4361
4367
|
}
|
|
4362
4368
|
}
|
|
4363
|
-
const
|
|
4364
|
-
sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(
|
|
4369
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
4370
|
+
sessionStorage.setItem(getTokenStorageKey3(walletAddress), JSON.stringify(record2));
|
|
4365
4371
|
}
|
|
4366
4372
|
function clearDriveToken(walletAddress) {
|
|
4367
4373
|
if (typeof window === "undefined") return;
|
|
@@ -4401,17 +4407,17 @@ function getRedirectUri3(callbackPath) {
|
|
|
4401
4407
|
}
|
|
4402
4408
|
function getAndClearOAuthState3() {
|
|
4403
4409
|
if (typeof window === "undefined") return null;
|
|
4404
|
-
const
|
|
4410
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY3);
|
|
4405
4411
|
sessionStorage.removeItem(CODE_STORAGE_KEY3);
|
|
4406
|
-
if (!
|
|
4412
|
+
if (!stored2) return null;
|
|
4407
4413
|
try {
|
|
4408
|
-
const parsed = JSON.parse(
|
|
4414
|
+
const parsed = JSON.parse(stored2);
|
|
4409
4415
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
4410
4416
|
return parsed.state;
|
|
4411
4417
|
}
|
|
4412
4418
|
} catch {
|
|
4413
4419
|
}
|
|
4414
|
-
return
|
|
4420
|
+
return stored2;
|
|
4415
4421
|
}
|
|
4416
4422
|
function isDriveCallback(callbackPath) {
|
|
4417
4423
|
if (typeof window === "undefined") return false;
|
|
@@ -4741,11 +4747,11 @@ function storePKCEState(pkce) {
|
|
|
4741
4747
|
}
|
|
4742
4748
|
function getAndClearPKCEState() {
|
|
4743
4749
|
if (typeof window === "undefined") return null;
|
|
4744
|
-
const
|
|
4750
|
+
const stored2 = sessionStorage.getItem(PKCE_STORAGE_KEY);
|
|
4745
4751
|
sessionStorage.removeItem(PKCE_STORAGE_KEY);
|
|
4746
|
-
if (!
|
|
4752
|
+
if (!stored2) return null;
|
|
4747
4753
|
try {
|
|
4748
|
-
return JSON.parse(
|
|
4754
|
+
return JSON.parse(stored2);
|
|
4749
4755
|
} catch {
|
|
4750
4756
|
return null;
|
|
4751
4757
|
}
|
|
@@ -4763,8 +4769,8 @@ async function storeTokenData4(data, walletAddress) {
|
|
|
4763
4769
|
} catch {
|
|
4764
4770
|
}
|
|
4765
4771
|
}
|
|
4766
|
-
const
|
|
4767
|
-
sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(
|
|
4772
|
+
const record2 = { wallet: walletAddress, token: data };
|
|
4773
|
+
sessionStorage.setItem(getTokenStorageKey4(walletAddress), JSON.stringify(record2));
|
|
4768
4774
|
}
|
|
4769
4775
|
async function getStoredTokenData4(walletAddress) {
|
|
4770
4776
|
if (typeof window === "undefined") return null;
|
|
@@ -4780,12 +4786,12 @@ async function getStoredTokenData4(walletAddress) {
|
|
|
4780
4786
|
cachedWalletAddress4 = null;
|
|
4781
4787
|
}
|
|
4782
4788
|
try {
|
|
4783
|
-
const
|
|
4784
|
-
if (
|
|
4789
|
+
const stored2 = localStorage.getItem(getTokenStorageKey4(walletAddress));
|
|
4790
|
+
if (stored2?.startsWith(ENCRYPTED_PREFIX5)) {
|
|
4785
4791
|
if (walletAddress && hasEncryptionKey(walletAddress)) {
|
|
4786
4792
|
try {
|
|
4787
4793
|
const cryptoKey = await getEncryptionKey(walletAddress);
|
|
4788
|
-
const encrypted =
|
|
4794
|
+
const encrypted = stored2.slice(ENCRYPTED_PREFIX5.length);
|
|
4789
4795
|
const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
|
|
4790
4796
|
const data = JSON.parse(decrypted);
|
|
4791
4797
|
if (data.accessToken) return data;
|
|
@@ -4894,12 +4900,12 @@ async function getClientRegistration(walletAddress) {
|
|
|
4894
4900
|
if (typeof window === "undefined") return null;
|
|
4895
4901
|
try {
|
|
4896
4902
|
const scopedKey = getClientRegistrationStorageKey(walletAddress);
|
|
4897
|
-
const
|
|
4898
|
-
if (
|
|
4903
|
+
const stored2 = localStorage.getItem(scopedKey);
|
|
4904
|
+
if (stored2?.startsWith(ENCRYPTED_PREFIX5)) {
|
|
4899
4905
|
if (walletAddress && hasEncryptionKey(walletAddress)) {
|
|
4900
4906
|
try {
|
|
4901
4907
|
const cryptoKey = await getEncryptionKey(walletAddress);
|
|
4902
|
-
const encrypted =
|
|
4908
|
+
const encrypted = stored2.slice(ENCRYPTED_PREFIX5.length);
|
|
4903
4909
|
const decrypted = await decryptDataWithKey(encrypted, cryptoKey);
|
|
4904
4910
|
const data = JSON.parse(decrypted);
|
|
4905
4911
|
if (data.clientId) {
|
|
@@ -4909,8 +4915,8 @@ async function getClientRegistration(walletAddress) {
|
|
|
4909
4915
|
}
|
|
4910
4916
|
}
|
|
4911
4917
|
}
|
|
4912
|
-
if (
|
|
4913
|
-
const data = JSON.parse(
|
|
4918
|
+
if (stored2 && !stored2.startsWith(ENCRYPTED_PREFIX5)) {
|
|
4919
|
+
const data = JSON.parse(stored2);
|
|
4914
4920
|
if (!data.clientId) return null;
|
|
4915
4921
|
return data;
|
|
4916
4922
|
}
|
|
@@ -6755,13 +6761,13 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
6755
6761
|
const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
6756
6762
|
return Promise.all(
|
|
6757
6763
|
topK.map(async ({ message, similarity }) => {
|
|
6758
|
-
const
|
|
6764
|
+
const stored2 = await messageRawToStored(
|
|
6759
6765
|
message,
|
|
6760
6766
|
ctx.walletAddress,
|
|
6761
6767
|
ctx.signMessage,
|
|
6762
6768
|
ctx.embeddedWalletSigner
|
|
6763
6769
|
);
|
|
6764
|
-
return { ...
|
|
6770
|
+
return { ...stored2, similarity };
|
|
6765
6771
|
})
|
|
6766
6772
|
);
|
|
6767
6773
|
}
|
|
@@ -6865,13 +6871,13 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
6865
6871
|
const storedById = new Map(
|
|
6866
6872
|
await Promise.all(
|
|
6867
6873
|
Array.from(uniqueMessages, async ([id, m]) => {
|
|
6868
|
-
const
|
|
6874
|
+
const stored2 = await messageRawToStored(
|
|
6869
6875
|
m,
|
|
6870
6876
|
ctx.walletAddress,
|
|
6871
6877
|
ctx.signMessage,
|
|
6872
6878
|
ctx.embeddedWalletSigner
|
|
6873
6879
|
);
|
|
6874
|
-
return [id,
|
|
6880
|
+
return [id, stored2];
|
|
6875
6881
|
})
|
|
6876
6882
|
)
|
|
6877
6883
|
);
|
|
@@ -6889,18 +6895,18 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
6889
6895
|
})
|
|
6890
6896
|
);
|
|
6891
6897
|
return topK.map(({ message, similarity, chunkTextSource }) => {
|
|
6892
|
-
const
|
|
6898
|
+
const stored2 = { ...storedById.get(message.id) };
|
|
6893
6899
|
let chunkText2;
|
|
6894
6900
|
if (chunkTextSource.kind === "chunk") {
|
|
6895
|
-
chunkText2 = resolveChunkText(
|
|
6901
|
+
chunkText2 = resolveChunkText(stored2.content, chunkTextSource.chunk, chunkTextSource.siblings);
|
|
6896
6902
|
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
6897
6903
|
const state = chunkStateByMsgId.get(message.id);
|
|
6898
6904
|
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
6899
|
-
chunkText2 = resolveChunkText(
|
|
6905
|
+
chunkText2 = resolveChunkText(stored2.content, chunk, state?.chunks);
|
|
6900
6906
|
} else {
|
|
6901
|
-
chunkText2 =
|
|
6907
|
+
chunkText2 = stored2.content;
|
|
6902
6908
|
}
|
|
6903
|
-
return { chunkText: chunkText2, message:
|
|
6909
|
+
return { chunkText: chunkText2, message: stored2, similarity };
|
|
6904
6910
|
});
|
|
6905
6911
|
}
|
|
6906
6912
|
async function getAllFilesOp(ctx, options) {
|
|
@@ -7250,7 +7256,7 @@ async function embedOne(text12, options, outer) {
|
|
|
7250
7256
|
}
|
|
7251
7257
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
7252
7258
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
7253
|
-
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
|
|
7259
|
+
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs, outer) {
|
|
7254
7260
|
const response = await withEmbeddingRetry(
|
|
7255
7261
|
() => withDeadline(
|
|
7256
7262
|
(signal) => postApiV1Embeddings({
|
|
@@ -7260,8 +7266,10 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
7260
7266
|
...signal && { signal }
|
|
7261
7267
|
}),
|
|
7262
7268
|
timeoutMs,
|
|
7263
|
-
"embedding batch request"
|
|
7264
|
-
|
|
7269
|
+
"embedding batch request",
|
|
7270
|
+
outer
|
|
7271
|
+
),
|
|
7272
|
+
outer
|
|
7265
7273
|
);
|
|
7266
7274
|
if (response.error) {
|
|
7267
7275
|
throw embeddingErrorFrom(response);
|
|
@@ -7279,6 +7287,11 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
7279
7287
|
}
|
|
7280
7288
|
async function generateEmbeddings(texts, options) {
|
|
7281
7289
|
if (texts.length === 0) return [];
|
|
7290
|
+
const total = options.totalTimeoutMs;
|
|
7291
|
+
if (total === void 0) return embedMany(texts, options, void 0);
|
|
7292
|
+
return withDeadline((signal) => embedMany(texts, options, signal), total, "embedding batch");
|
|
7293
|
+
}
|
|
7294
|
+
async function embedMany(texts, options, outer) {
|
|
7282
7295
|
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
7283
7296
|
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
7284
7297
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
@@ -7299,7 +7312,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
7299
7312
|
if (uncachedTexts.length === 0) {
|
|
7300
7313
|
return results;
|
|
7301
7314
|
}
|
|
7302
|
-
const headers = await resolveAuthHeaders(options);
|
|
7315
|
+
const headers = await resolveAuthHeaders(options, outer);
|
|
7316
|
+
if (outer?.aborted) throw outer.reason;
|
|
7303
7317
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
7304
7318
|
let newEmbeddings;
|
|
7305
7319
|
if (uncachedTexts.length <= chunkSize) {
|
|
@@ -7310,7 +7324,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
7310
7324
|
embeddingModel,
|
|
7311
7325
|
options.onUsage,
|
|
7312
7326
|
options.maskInput,
|
|
7313
|
-
timeoutMs
|
|
7327
|
+
timeoutMs,
|
|
7328
|
+
outer
|
|
7314
7329
|
);
|
|
7315
7330
|
} else {
|
|
7316
7331
|
const chunks = [];
|
|
@@ -7321,6 +7336,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
7321
7336
|
let nextIndex = 0;
|
|
7322
7337
|
const worker = async () => {
|
|
7323
7338
|
while (nextIndex < chunks.length) {
|
|
7339
|
+
if (outer?.aborted) throw outer.reason;
|
|
7324
7340
|
const idx = nextIndex++;
|
|
7325
7341
|
allEmbeddings[idx] = await generateEmbeddingsBatch(
|
|
7326
7342
|
chunks[idx],
|
|
@@ -7329,7 +7345,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
7329
7345
|
embeddingModel,
|
|
7330
7346
|
options.onUsage,
|
|
7331
7347
|
options.maskInput,
|
|
7332
|
-
timeoutMs
|
|
7348
|
+
timeoutMs,
|
|
7349
|
+
outer
|
|
7333
7350
|
);
|
|
7334
7351
|
}
|
|
7335
7352
|
};
|
|
@@ -7340,6 +7357,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
7340
7357
|
await Promise.all(workers);
|
|
7341
7358
|
newEmbeddings = allEmbeddings.flat();
|
|
7342
7359
|
}
|
|
7360
|
+
if (outer?.aborted) throw outer.reason;
|
|
7343
7361
|
for (let i = 0; i < uncachedIndices.length; i++) {
|
|
7344
7362
|
const f32Embedding = Float32Array.from(newEmbeddings[i]);
|
|
7345
7363
|
results[uncachedIndices[i]] = Array.from(f32Embedding);
|
|
@@ -12513,15 +12531,15 @@ function createSummaryContext(database) {
|
|
|
12513
12531
|
summariesCollection: database.get("conversation_summaries")
|
|
12514
12532
|
};
|
|
12515
12533
|
}
|
|
12516
|
-
function modelToStored(
|
|
12534
|
+
function modelToStored(record2) {
|
|
12517
12535
|
return {
|
|
12518
|
-
uniqueId:
|
|
12519
|
-
conversationId:
|
|
12520
|
-
summary:
|
|
12521
|
-
summarizedUpTo:
|
|
12522
|
-
tokenCount:
|
|
12523
|
-
createdAt:
|
|
12524
|
-
updatedAt:
|
|
12536
|
+
uniqueId: record2.id,
|
|
12537
|
+
conversationId: record2.conversationId,
|
|
12538
|
+
summary: record2.summary,
|
|
12539
|
+
summarizedUpTo: record2.summarizedUpTo,
|
|
12540
|
+
tokenCount: record2.tokenCount,
|
|
12541
|
+
createdAt: record2.createdAt,
|
|
12542
|
+
updatedAt: record2.updatedAt
|
|
12525
12543
|
};
|
|
12526
12544
|
}
|
|
12527
12545
|
async function getConversationSummaryOp(ctx, conversationId) {
|
|
@@ -12530,17 +12548,17 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
12530
12548
|
return modelToStored(results[0]);
|
|
12531
12549
|
}
|
|
12532
12550
|
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
12533
|
-
let
|
|
12551
|
+
let record2;
|
|
12534
12552
|
await ctx.database.write(async () => {
|
|
12535
12553
|
const existing = await ctx.summariesCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId)).fetch();
|
|
12536
12554
|
if (existing.length > 0) {
|
|
12537
|
-
|
|
12555
|
+
record2 = await existing[0].update((rec) => {
|
|
12538
12556
|
rec.summary = summary;
|
|
12539
12557
|
rec.summarizedUpTo = summarizedUpTo;
|
|
12540
12558
|
rec.tokenCount = tokenCount;
|
|
12541
12559
|
});
|
|
12542
12560
|
} else {
|
|
12543
|
-
|
|
12561
|
+
record2 = await ctx.summariesCollection.create((rec) => {
|
|
12544
12562
|
rec.conversationId = conversationId;
|
|
12545
12563
|
rec.summary = summary;
|
|
12546
12564
|
rec.summarizedUpTo = summarizedUpTo;
|
|
@@ -12548,13 +12566,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
|
|
|
12548
12566
|
});
|
|
12549
12567
|
}
|
|
12550
12568
|
});
|
|
12551
|
-
return modelToStored(
|
|
12569
|
+
return modelToStored(record2);
|
|
12552
12570
|
}
|
|
12553
12571
|
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
12554
12572
|
await ctx.database.write(async () => {
|
|
12555
12573
|
const existing = await ctx.summariesCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId)).fetch();
|
|
12556
|
-
for (const
|
|
12557
|
-
await
|
|
12574
|
+
for (const record2 of existing) {
|
|
12575
|
+
await record2.destroyPermanently();
|
|
12558
12576
|
}
|
|
12559
12577
|
});
|
|
12560
12578
|
}
|
|
@@ -12747,25 +12765,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
12747
12765
|
const kindBackfills = existing.filter((e) => {
|
|
12748
12766
|
const incoming = kindByName.get(e.canonicalName);
|
|
12749
12767
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
12750
|
-
}).map((
|
|
12768
|
+
}).map((record2) => ({ record: record2, kind: kindByName.get(record2.canonicalName) }));
|
|
12751
12769
|
const missing = unique.filter((n) => !existingNames.has(n));
|
|
12752
12770
|
const created = missing.map(
|
|
12753
|
-
(name) => ctx.entityCollection.prepareCreate((
|
|
12754
|
-
|
|
12771
|
+
(name) => ctx.entityCollection.prepareCreate((record2) => {
|
|
12772
|
+
record2._setRaw("canonical_name", name);
|
|
12755
12773
|
const kind = kindByName.get(name);
|
|
12756
|
-
if (kind !== void 0)
|
|
12774
|
+
if (kind !== void 0) record2._setRaw("kind", kind);
|
|
12757
12775
|
})
|
|
12758
12776
|
);
|
|
12759
12777
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
12760
|
-
for (const
|
|
12761
|
-
for (const { record, kind } of kindBackfills) {
|
|
12762
|
-
out.set(
|
|
12778
|
+
for (const record2 of created) out.set(record2.canonicalName, entityToStored(record2));
|
|
12779
|
+
for (const { record: record2, kind } of kindBackfills) {
|
|
12780
|
+
out.set(record2.canonicalName, { ...entityToStored(record2), kind });
|
|
12763
12781
|
}
|
|
12764
12782
|
return { entities: out, operations: created, kindBackfills };
|
|
12765
12783
|
}
|
|
12766
12784
|
function prepareKindBackfills(backfills) {
|
|
12767
12785
|
return backfills.map(
|
|
12768
|
-
({ record, kind }) =>
|
|
12786
|
+
({ record: record2, kind }) => record2.prepareUpdate((r) => {
|
|
12769
12787
|
r._setRaw("kind", kind);
|
|
12770
12788
|
})
|
|
12771
12789
|
);
|
|
@@ -12796,10 +12814,10 @@ function displayNamesOf(entities) {
|
|
|
12796
12814
|
}
|
|
12797
12815
|
return out;
|
|
12798
12816
|
}
|
|
12799
|
-
function topicsEqual(
|
|
12800
|
-
if (
|
|
12817
|
+
function topicsEqual(stored2, computed) {
|
|
12818
|
+
if (stored2 === null || stored2.length !== computed.length) return false;
|
|
12801
12819
|
const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
|
|
12802
|
-
const storedKeys =
|
|
12820
|
+
const storedKeys = stored2.map(key).sort();
|
|
12803
12821
|
const computedKeys = computed.map(key).sort();
|
|
12804
12822
|
return storedKeys.every((k, i) => k === computedKeys[i]);
|
|
12805
12823
|
}
|
|
@@ -12865,10 +12883,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
12865
12883
|
return;
|
|
12866
12884
|
}
|
|
12867
12885
|
const linkOps = toCreate.map(
|
|
12868
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
if (userId !== void 0)
|
|
12886
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
|
|
12887
|
+
record2._setRaw("memory_id", memoryId);
|
|
12888
|
+
record2._setRaw("entity_id", e.uniqueId);
|
|
12889
|
+
if (userId !== void 0) record2._setRaw("user_id", userId);
|
|
12872
12890
|
})
|
|
12873
12891
|
);
|
|
12874
12892
|
await ctx.database.batch(
|
|
@@ -12936,10 +12954,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
12936
12954
|
...entityOps,
|
|
12937
12955
|
...prepareKindBackfills(kindBackfills),
|
|
12938
12956
|
...toCreate.map(
|
|
12939
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
if (userId !== void 0)
|
|
12957
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
|
|
12958
|
+
record2._setRaw("memory_id", memoryId);
|
|
12959
|
+
record2._setRaw("entity_id", e.uniqueId);
|
|
12960
|
+
if (userId !== void 0) record2._setRaw("user_id", userId);
|
|
12943
12961
|
})
|
|
12944
12962
|
),
|
|
12945
12963
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
@@ -13140,6 +13158,15 @@ __decorateClass([
|
|
|
13140
13158
|
__decorateClass([
|
|
13141
13159
|
(0, import_decorators6.text)("scope")
|
|
13142
13160
|
], VaultMemory.prototype, "scope", 2);
|
|
13161
|
+
__decorateClass([
|
|
13162
|
+
(0, import_decorators6.field)("kind")
|
|
13163
|
+
], VaultMemory.prototype, "kind", 2);
|
|
13164
|
+
__decorateClass([
|
|
13165
|
+
(0, import_decorators6.field)("kind_value")
|
|
13166
|
+
], VaultMemory.prototype, "kindValue", 2);
|
|
13167
|
+
__decorateClass([
|
|
13168
|
+
(0, import_decorators6.field)("level")
|
|
13169
|
+
], VaultMemory.prototype, "level", 2);
|
|
13143
13170
|
__decorateClass([
|
|
13144
13171
|
(0, import_decorators6.field)("folder_id")
|
|
13145
13172
|
], VaultMemory.prototype, "folderId", 2);
|
|
@@ -13365,7 +13392,7 @@ __decorateClass([
|
|
|
13365
13392
|
], VaultFolder.prototype, "context", 2);
|
|
13366
13393
|
|
|
13367
13394
|
// src/lib/db/schema.ts
|
|
13368
|
-
var SDK_SCHEMA_VERSION =
|
|
13395
|
+
var SDK_SCHEMA_VERSION = 48;
|
|
13369
13396
|
var sdkSchema = (0, import_watermelondb19.appSchema)({
|
|
13370
13397
|
version: SDK_SCHEMA_VERSION,
|
|
13371
13398
|
tables: [
|
|
@@ -13460,6 +13487,9 @@ var sdkSchema = (0, import_watermelondb19.appSchema)({
|
|
|
13460
13487
|
columns: [
|
|
13461
13488
|
{ name: "content", type: "string" },
|
|
13462
13489
|
{ name: "scope", type: "string", isIndexed: true },
|
|
13490
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
13491
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
13492
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true },
|
|
13463
13493
|
{ name: "folder_id", type: "string", isOptional: true, isIndexed: true },
|
|
13464
13494
|
{ name: "created_at", type: "number", isIndexed: true },
|
|
13465
13495
|
{ name: "updated_at", type: "number", isIndexed: true },
|
|
@@ -14136,6 +14166,22 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
|
|
|
14136
14166
|
]
|
|
14137
14167
|
})
|
|
14138
14168
|
]
|
|
14169
|
+
},
|
|
14170
|
+
{
|
|
14171
|
+
toVersion: 48,
|
|
14172
|
+
steps: [
|
|
14173
|
+
(0, import_migrations2.addColumns)({
|
|
14174
|
+
table: "memory_vault",
|
|
14175
|
+
columns: [
|
|
14176
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
14177
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
14178
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true }
|
|
14179
|
+
]
|
|
14180
|
+
}),
|
|
14181
|
+
(0, import_migrations2.unsafeExecuteSql)(
|
|
14182
|
+
"UPDATE memory_vault SET level = CASE WHEN scope IN ('shared', 'public') THEN 'matching' ELSE 'private' END WHERE level IS NULL;"
|
|
14183
|
+
)
|
|
14184
|
+
]
|
|
14139
14185
|
}
|
|
14140
14186
|
]
|
|
14141
14187
|
});
|
|
@@ -15009,13 +15055,13 @@ async function relinkMisclassifiedVideosOp(ctx, walletAddress) {
|
|
|
15009
15055
|
toRelink.push({ media, ext: mime.split("/")[1] || "mp4" });
|
|
15010
15056
|
continue;
|
|
15011
15057
|
}
|
|
15012
|
-
const
|
|
15058
|
+
const stored2 = await mediaToStored(
|
|
15013
15059
|
media,
|
|
15014
15060
|
ctx.walletAddress,
|
|
15015
15061
|
ctx.signMessage,
|
|
15016
15062
|
ctx.embeddedWalletSigner
|
|
15017
15063
|
);
|
|
15018
|
-
const ext = videoExtensionOf(
|
|
15064
|
+
const ext = videoExtensionOf(stored2.sourceUrl) ?? videoExtensionOf(stored2.name);
|
|
15019
15065
|
if (ext) {
|
|
15020
15066
|
toRelink.push({ media, ext });
|
|
15021
15067
|
}
|
|
@@ -15277,13 +15323,54 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
15277
15323
|
}
|
|
15278
15324
|
}
|
|
15279
15325
|
const decryptedContent = await decryptField(memory.content, address);
|
|
15326
|
+
const decryptedKindValue = typeof memory.kindValue === "string" ? await decryptField(memory.kindValue, address) : memory.kindValue;
|
|
15280
15327
|
return {
|
|
15281
15328
|
...memory,
|
|
15282
|
-
content: decryptedContent
|
|
15329
|
+
content: decryptedContent,
|
|
15330
|
+
...decryptedKindValue !== void 0 && { kindValue: decryptedKindValue }
|
|
15283
15331
|
};
|
|
15284
15332
|
}
|
|
15285
15333
|
|
|
15286
15334
|
// src/lib/db/memoryVault/types.ts
|
|
15335
|
+
var MEMORY_KINDS = [
|
|
15336
|
+
"display_name",
|
|
15337
|
+
"birth_date",
|
|
15338
|
+
"bio",
|
|
15339
|
+
"occupation",
|
|
15340
|
+
"interest",
|
|
15341
|
+
"gender",
|
|
15342
|
+
"height_cm",
|
|
15343
|
+
"looking_for",
|
|
15344
|
+
"politics",
|
|
15345
|
+
"religion",
|
|
15346
|
+
"ethnicity",
|
|
15347
|
+
"smoking",
|
|
15348
|
+
"drinking",
|
|
15349
|
+
"exercise",
|
|
15350
|
+
"sexuality",
|
|
15351
|
+
"prompt"
|
|
15352
|
+
];
|
|
15353
|
+
var MEMORY_LEVELS = ["private", "matching", "profile"];
|
|
15354
|
+
var MemoryLevelError = class extends Error {
|
|
15355
|
+
constructor(message) {
|
|
15356
|
+
super(message);
|
|
15357
|
+
this.name = "MemoryLevelError";
|
|
15358
|
+
}
|
|
15359
|
+
};
|
|
15360
|
+
var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
|
|
15361
|
+
function levelFromScope(scope) {
|
|
15362
|
+
return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
|
|
15363
|
+
}
|
|
15364
|
+
function scopeForLevel(level) {
|
|
15365
|
+
return level === "private" ? "private" : "shared";
|
|
15366
|
+
}
|
|
15367
|
+
function resolveMemoryLevel(level, scope) {
|
|
15368
|
+
return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
|
|
15369
|
+
}
|
|
15370
|
+
function levelForScopeChange(current, nextScope) {
|
|
15371
|
+
const implied = levelFromScope(nextScope);
|
|
15372
|
+
return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
|
|
15373
|
+
}
|
|
15287
15374
|
function parseMedia(value) {
|
|
15288
15375
|
if (typeof value !== "string" || value === "") return null;
|
|
15289
15376
|
try {
|
|
@@ -15313,8 +15400,58 @@ function visibilityConditions(requested) {
|
|
|
15313
15400
|
if (excluded.length === 0) return [];
|
|
15314
15401
|
return [import_watermelondb23.Q.or(import_watermelondb23.Q.where("visibility", null), import_watermelondb23.Q.where("visibility", import_watermelondb23.Q.notIn(excluded)))];
|
|
15315
15402
|
}
|
|
15316
|
-
function
|
|
15317
|
-
return
|
|
15403
|
+
function isKinded(record2) {
|
|
15404
|
+
return record2.kind !== null && record2.kind !== void 0;
|
|
15405
|
+
}
|
|
15406
|
+
function assertValidKindLevel(kind, level) {
|
|
15407
|
+
const hasKind = kind !== null && kind !== void 0;
|
|
15408
|
+
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
15409
|
+
throw new MemoryLevelError(`Unknown memory kind: ${kind}`);
|
|
15410
|
+
}
|
|
15411
|
+
if (level !== void 0 && !MEMORY_LEVELS.includes(level)) {
|
|
15412
|
+
throw new MemoryLevelError(`Unknown memory level: ${level}`);
|
|
15413
|
+
}
|
|
15414
|
+
if (level === "profile" && !hasKind) {
|
|
15415
|
+
throw new MemoryLevelError("Only a memory with a kind can be at level 'profile'");
|
|
15416
|
+
}
|
|
15417
|
+
}
|
|
15418
|
+
function resolveCreateLevel(opts) {
|
|
15419
|
+
if (opts.level !== void 0) return { level: opts.level, scope: scopeForLevel(opts.level) };
|
|
15420
|
+
if (opts.scope !== void 0) return { level: levelFromScope(opts.scope), scope: opts.scope };
|
|
15421
|
+
return { level: "private", scope: "private" };
|
|
15422
|
+
}
|
|
15423
|
+
async function encryptKindValue(ctx, value) {
|
|
15424
|
+
if (typeof value !== "string" || !ctx.walletAddress || !ctx.signMessage) return value;
|
|
15425
|
+
return encryptVaultMemoryContent(
|
|
15426
|
+
value,
|
|
15427
|
+
ctx.walletAddress,
|
|
15428
|
+
ctx.signMessage,
|
|
15429
|
+
ctx.embeddedWalletSigner
|
|
15430
|
+
);
|
|
15431
|
+
}
|
|
15432
|
+
function levelConditions(requested) {
|
|
15433
|
+
if (!requested?.length) return [];
|
|
15434
|
+
const published = ["shared", "public"];
|
|
15435
|
+
const wantsMatching = requested.includes("matching");
|
|
15436
|
+
const wantsPrivate = requested.includes("private");
|
|
15437
|
+
const unresolved = import_watermelondb23.Q.or(import_watermelondb23.Q.where("level", null), import_watermelondb23.Q.where("level", import_watermelondb23.Q.notIn([...MEMORY_LEVELS])));
|
|
15438
|
+
const byLevel = import_watermelondb23.Q.where("level", import_watermelondb23.Q.oneOf([...requested]));
|
|
15439
|
+
if (wantsMatching && wantsPrivate) return [import_watermelondb23.Q.or(byLevel, unresolved)];
|
|
15440
|
+
if (wantsMatching) {
|
|
15441
|
+
return [import_watermelondb23.Q.or(byLevel, import_watermelondb23.Q.and(unresolved, import_watermelondb23.Q.where("scope", import_watermelondb23.Q.oneOf(published))))];
|
|
15442
|
+
}
|
|
15443
|
+
if (wantsPrivate) {
|
|
15444
|
+
return [
|
|
15445
|
+
import_watermelondb23.Q.or(
|
|
15446
|
+
byLevel,
|
|
15447
|
+
import_watermelondb23.Q.and(unresolved, import_watermelondb23.Q.or(import_watermelondb23.Q.where("scope", null), import_watermelondb23.Q.where("scope", import_watermelondb23.Q.notIn(published))))
|
|
15448
|
+
)
|
|
15449
|
+
];
|
|
15450
|
+
}
|
|
15451
|
+
return [byLevel];
|
|
15452
|
+
}
|
|
15453
|
+
function isOwnedByCtxUser(ctx, record2) {
|
|
15454
|
+
return ctx.userId === void 0 || record2.userId === ctx.userId;
|
|
15318
15455
|
}
|
|
15319
15456
|
function baseVaultConditions(ctx, options) {
|
|
15320
15457
|
return [
|
|
@@ -15356,6 +15493,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
15356
15493
|
uniqueId: memory.id,
|
|
15357
15494
|
content: memory.content,
|
|
15358
15495
|
scope: memory.scope,
|
|
15496
|
+
kind: memory.kind ?? null,
|
|
15497
|
+
kindValue: memory.kindValue ?? null,
|
|
15498
|
+
level: resolveMemoryLevel(memory.level, memory.scope),
|
|
15359
15499
|
folderId: memory.folderId ?? null,
|
|
15360
15500
|
userId: memory.userId ?? null,
|
|
15361
15501
|
embedding: memory.embedding ?? null,
|
|
@@ -15394,42 +15534,48 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
15394
15534
|
}
|
|
15395
15535
|
return raw;
|
|
15396
15536
|
}
|
|
15397
|
-
function populateNewVaultMemory(
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
-
|
|
15402
|
-
|
|
15537
|
+
function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue) {
|
|
15538
|
+
const { level, scope } = resolveCreateLevel(opts);
|
|
15539
|
+
record2._setRaw("content", encryptedContent);
|
|
15540
|
+
record2._setRaw("scope", scope);
|
|
15541
|
+
record2._setRaw("level", level);
|
|
15542
|
+
record2._setRaw("kind", opts.kind ?? null);
|
|
15543
|
+
record2._setRaw("kind_value", encryptedKindValue ?? null);
|
|
15544
|
+
record2._setRaw("folder_id", opts.folderId ?? null);
|
|
15545
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
15546
|
+
record2._setRaw("is_deleted", false);
|
|
15403
15547
|
if (opts.embedding !== void 0) {
|
|
15404
|
-
|
|
15405
|
-
|
|
15548
|
+
record2._setRaw("embedding", opts.embedding);
|
|
15549
|
+
record2._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
15406
15550
|
}
|
|
15407
15551
|
if (opts.sourceChunkIds !== void 0) {
|
|
15408
|
-
|
|
15552
|
+
record2._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
|
|
15409
15553
|
}
|
|
15410
|
-
|
|
15411
|
-
|
|
15554
|
+
record2._setRaw("proof_count", opts.proofCount ?? 1);
|
|
15555
|
+
record2._setRaw("source", opts.source ?? "manual");
|
|
15412
15556
|
if (opts.eventTime) {
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15557
|
+
record2._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
15558
|
+
record2._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
15559
|
+
record2._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
15416
15560
|
}
|
|
15417
15561
|
if (opts.factType !== void 0) {
|
|
15418
|
-
|
|
15562
|
+
record2._setRaw("fact_type", opts.factType);
|
|
15419
15563
|
}
|
|
15420
15564
|
if (opts.trustTier !== void 0) {
|
|
15421
|
-
|
|
15565
|
+
record2._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
15422
15566
|
}
|
|
15423
|
-
|
|
15424
|
-
|
|
15567
|
+
record2._setRaw("visibility", opts.visibility ?? "private");
|
|
15568
|
+
record2._setRaw(
|
|
15425
15569
|
"published_at",
|
|
15426
15570
|
opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
|
|
15427
15571
|
);
|
|
15428
15572
|
if (opts.geohash !== void 0) {
|
|
15429
|
-
|
|
15573
|
+
record2._setRaw("geohash", opts.geohash);
|
|
15430
15574
|
}
|
|
15431
15575
|
}
|
|
15432
15576
|
async function createVaultMemoryOp(ctx, opts) {
|
|
15577
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
15578
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
15433
15579
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15434
15580
|
opts.content,
|
|
15435
15581
|
ctx.walletAddress,
|
|
@@ -15440,13 +15586,15 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
15440
15586
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
15441
15587
|
throw new Error("Memory source is no longer eligible");
|
|
15442
15588
|
return ctx.vaultMemoryCollection.create(
|
|
15443
|
-
(
|
|
15589
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
15444
15590
|
);
|
|
15445
15591
|
});
|
|
15446
15592
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
15447
15593
|
}
|
|
15448
15594
|
async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
15449
15595
|
if (!targetId) return { created: null, retired: false };
|
|
15596
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
15597
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
15450
15598
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15451
15599
|
opts.content,
|
|
15452
15600
|
ctx.walletAddress,
|
|
@@ -15463,9 +15611,10 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
15463
15611
|
} catch {
|
|
15464
15612
|
return;
|
|
15465
15613
|
}
|
|
15466
|
-
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target))
|
|
15614
|
+
if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
|
|
15615
|
+
return;
|
|
15467
15616
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
15468
|
-
(
|
|
15617
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
15469
15618
|
);
|
|
15470
15619
|
await target.update((r) => {
|
|
15471
15620
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -15529,6 +15678,10 @@ async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
|
|
|
15529
15678
|
}
|
|
15530
15679
|
async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
15531
15680
|
if (optionsArray.length === 0) return [];
|
|
15681
|
+
for (const opts of optionsArray) assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
15682
|
+
const encryptedKindValues = await Promise.all(
|
|
15683
|
+
optionsArray.map((opts) => encryptKindValue(ctx, opts.kindValue))
|
|
15684
|
+
);
|
|
15532
15685
|
const encryptedContents = await Promise.all(
|
|
15533
15686
|
optionsArray.map(async (opts) => {
|
|
15534
15687
|
if (ctx.walletAddress && ctx.signMessage) {
|
|
@@ -15547,7 +15700,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
15547
15700
|
throw new Error("Memory source is no longer eligible");
|
|
15548
15701
|
const prepared = optionsArray.map(
|
|
15549
15702
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
15550
|
-
(
|
|
15703
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
15551
15704
|
)
|
|
15552
15705
|
);
|
|
15553
15706
|
await ctx.database.batch(...prepared);
|
|
@@ -15555,16 +15708,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
15555
15708
|
});
|
|
15556
15709
|
return Promise.all(
|
|
15557
15710
|
created.map(
|
|
15558
|
-
(
|
|
15711
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
15559
15712
|
)
|
|
15560
15713
|
);
|
|
15561
15714
|
}
|
|
15562
15715
|
async function getVaultMemoryOp(ctx, id) {
|
|
15563
15716
|
try {
|
|
15564
|
-
const
|
|
15565
|
-
if (
|
|
15717
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
15718
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15566
15719
|
return vaultMemoryToStored(
|
|
15567
|
-
|
|
15720
|
+
record2,
|
|
15568
15721
|
ctx.walletAddress,
|
|
15569
15722
|
ctx.signMessage,
|
|
15570
15723
|
ctx.embeddedWalletSigner
|
|
@@ -15590,6 +15743,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
15590
15743
|
uniqueId: raw.id,
|
|
15591
15744
|
content: raw.content ?? "",
|
|
15592
15745
|
scope: raw.scope ?? "",
|
|
15746
|
+
kind: raw.kind ?? null,
|
|
15747
|
+
kindValue: raw.kind_value ?? null,
|
|
15748
|
+
level: resolveMemoryLevel(raw.level, raw.scope),
|
|
15593
15749
|
folderId: raw.folder_id ?? null,
|
|
15594
15750
|
userId: raw.user_id ?? null,
|
|
15595
15751
|
embedding: raw.embedding ?? null,
|
|
@@ -15622,17 +15778,19 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
15622
15778
|
};
|
|
15623
15779
|
}
|
|
15624
15780
|
async function vaultMemoryRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner) {
|
|
15625
|
-
const
|
|
15781
|
+
const stored2 = vaultMemoryRawToStoredRaw(raw);
|
|
15626
15782
|
if (walletAddress) {
|
|
15627
|
-
return decryptVaultMemoryFields(
|
|
15783
|
+
return decryptVaultMemoryFields(stored2, walletAddress, signMessage, embeddedWalletSigner);
|
|
15628
15784
|
}
|
|
15629
|
-
return
|
|
15785
|
+
return stored2;
|
|
15630
15786
|
}
|
|
15631
15787
|
async function getAllVaultMemoriesOp(ctx, options) {
|
|
15632
15788
|
const conditions = [
|
|
15633
15789
|
...baseVaultConditions(ctx, options),
|
|
15634
15790
|
...options?.scopes?.length ? [import_watermelondb23.Q.where("scope", import_watermelondb23.Q.oneOf(options.scopes))] : [],
|
|
15635
15791
|
...visibilityConditions(options?.visibility),
|
|
15792
|
+
...levelConditions(options?.levels),
|
|
15793
|
+
...options?.kinds?.length ? [import_watermelondb23.Q.where("kind", import_watermelondb23.Q.oneOf(options.kinds))] : [],
|
|
15636
15794
|
...options?.folderId !== void 0 ? [import_watermelondb23.Q.where("folder_id", options.folderId)] : [],
|
|
15637
15795
|
...options?.factTypes?.length ? [import_watermelondb23.Q.where("fact_type", import_watermelondb23.Q.oneOf(options.factTypes))] : [],
|
|
15638
15796
|
import_watermelondb23.Q.sortBy(options?.since ? "updated_at" : "created_at", import_watermelondb23.Q.desc),
|
|
@@ -15778,13 +15936,13 @@ async function getVaultMemoriesByIdsOp(ctx, ids, options) {
|
|
|
15778
15936
|
async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
15779
15937
|
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
|
|
15780
15938
|
return mapInBatches(results, async (raw) => {
|
|
15781
|
-
const
|
|
15939
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
15782
15940
|
raw,
|
|
15783
15941
|
ctx.walletAddress,
|
|
15784
15942
|
ctx.signMessage,
|
|
15785
15943
|
ctx.embeddedWalletSigner
|
|
15786
15944
|
);
|
|
15787
|
-
return
|
|
15945
|
+
return stored2.content;
|
|
15788
15946
|
});
|
|
15789
15947
|
}
|
|
15790
15948
|
async function countActiveVaultMemoriesOp(ctx) {
|
|
@@ -15799,6 +15957,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15799
15957
|
try {
|
|
15800
15958
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
15801
15959
|
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
15960
|
+
if (opts.freeFormOnly && isKinded(probe)) return null;
|
|
15961
|
+
const levelAfter = (current) => {
|
|
15962
|
+
if (opts.level !== void 0) return opts.level;
|
|
15963
|
+
if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
|
|
15964
|
+
return levelForScopeChange(current, opts.scope);
|
|
15965
|
+
};
|
|
15966
|
+
assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
|
|
15967
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
15802
15968
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15803
15969
|
opts.content,
|
|
15804
15970
|
ctx.walletAddress,
|
|
@@ -15806,30 +15972,43 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15806
15972
|
ctx.embeddedWalletSigner
|
|
15807
15973
|
) : opts.content;
|
|
15808
15974
|
let stale = false;
|
|
15809
|
-
const
|
|
15810
|
-
const originalUpdatedAt =
|
|
15975
|
+
const record2 = probe;
|
|
15976
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15811
15977
|
await ctx.database.write(async () => {
|
|
15812
15978
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
15813
15979
|
throw new Error("Memory source is no longer eligible");
|
|
15814
|
-
if (
|
|
15980
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
15815
15981
|
stale = true;
|
|
15816
15982
|
return;
|
|
15817
15983
|
}
|
|
15984
|
+
const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
|
|
15985
|
+
const nextLevel = levelAfter(record2);
|
|
15986
|
+
assertValidKindLevel(nextKind, nextLevel);
|
|
15818
15987
|
let observedSources = [];
|
|
15819
15988
|
let replayedObservation = false;
|
|
15820
15989
|
if (opts.observationSourceIds?.length) {
|
|
15821
15990
|
try {
|
|
15822
|
-
const parsed = JSON.parse(
|
|
15991
|
+
const parsed = JSON.parse(record2.sourceChunkIds ?? "[]");
|
|
15823
15992
|
if (Array.isArray(parsed))
|
|
15824
15993
|
observedSources = parsed.filter((id2) => typeof id2 === "string");
|
|
15825
15994
|
} catch {
|
|
15826
15995
|
}
|
|
15827
15996
|
replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
|
|
15828
15997
|
}
|
|
15829
|
-
await
|
|
15998
|
+
await record2.update((r) => {
|
|
15830
15999
|
r._setRaw("content", encryptedContent);
|
|
15831
|
-
if (opts.
|
|
16000
|
+
if (opts.level !== void 0) {
|
|
16001
|
+
r._setRaw("level", nextLevel);
|
|
16002
|
+
r._setRaw("scope", scopeForLevel(nextLevel));
|
|
16003
|
+
} else if (opts.scope !== void 0) {
|
|
15832
16004
|
r._setRaw("scope", opts.scope);
|
|
16005
|
+
r._setRaw("level", nextLevel);
|
|
16006
|
+
}
|
|
16007
|
+
if (opts.kind !== void 0) {
|
|
16008
|
+
r._setRaw("kind", opts.kind);
|
|
16009
|
+
}
|
|
16010
|
+
if (encryptedKindValue !== void 0) {
|
|
16011
|
+
r._setRaw("kind_value", encryptedKindValue);
|
|
15833
16012
|
}
|
|
15834
16013
|
if (opts.folderId !== void 0) {
|
|
15835
16014
|
r._setRaw("folder_id", opts.folderId);
|
|
@@ -15883,12 +16062,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15883
16062
|
});
|
|
15884
16063
|
if (stale) return null;
|
|
15885
16064
|
return vaultMemoryToStored(
|
|
15886
|
-
|
|
16065
|
+
record2,
|
|
15887
16066
|
ctx.walletAddress,
|
|
15888
16067
|
ctx.signMessage,
|
|
15889
16068
|
ctx.embeddedWalletSigner
|
|
15890
16069
|
);
|
|
15891
|
-
} catch {
|
|
16070
|
+
} catch (err) {
|
|
16071
|
+
if (err instanceof MemoryLevelError) throw err;
|
|
15892
16072
|
return null;
|
|
15893
16073
|
}
|
|
15894
16074
|
}
|
|
@@ -15897,21 +16077,21 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
15897
16077
|
if (!entityCtx) {
|
|
15898
16078
|
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
15899
16079
|
}
|
|
15900
|
-
let
|
|
16080
|
+
let record2;
|
|
15901
16081
|
try {
|
|
15902
|
-
|
|
16082
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
15903
16083
|
} catch {
|
|
15904
16084
|
return null;
|
|
15905
16085
|
}
|
|
15906
|
-
if (
|
|
16086
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15907
16087
|
let stale = false;
|
|
15908
|
-
const originalUpdatedAt =
|
|
16088
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15909
16089
|
await ctx.database.write(async (writer) => {
|
|
15910
|
-
if (
|
|
16090
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15911
16091
|
stale = true;
|
|
15912
16092
|
return;
|
|
15913
16093
|
}
|
|
15914
|
-
await
|
|
16094
|
+
await record2.update((r) => {
|
|
15915
16095
|
r._setRaw("topics_user_managed", true);
|
|
15916
16096
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
15917
16097
|
});
|
|
@@ -15935,25 +16115,25 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
15935
16115
|
);
|
|
15936
16116
|
});
|
|
15937
16117
|
if (stale) return null;
|
|
15938
|
-
return vaultMemoryToStored(
|
|
16118
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
15939
16119
|
}
|
|
15940
16120
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
15941
|
-
let
|
|
16121
|
+
let record2;
|
|
15942
16122
|
try {
|
|
15943
|
-
|
|
16123
|
+
record2 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
15944
16124
|
} catch {
|
|
15945
16125
|
return false;
|
|
15946
16126
|
}
|
|
15947
|
-
if (
|
|
15948
|
-
const originalUpdatedAt =
|
|
16127
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16128
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15949
16129
|
let cleared = false;
|
|
15950
16130
|
await ctx.database.write(async () => {
|
|
15951
|
-
if (options?.unlessTopicsRecorded && parseTopics(
|
|
16131
|
+
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
15952
16132
|
cleared = true;
|
|
15953
|
-
await
|
|
16133
|
+
await record2.update((r) => {
|
|
15954
16134
|
r._setRaw("topics_user_managed", false);
|
|
15955
16135
|
r._setRaw("topics_extracted_version", null);
|
|
15956
|
-
if (
|
|
16136
|
+
if (record2.topicsExtractedAt === null) {
|
|
15957
16137
|
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
15958
16138
|
}
|
|
15959
16139
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -15962,22 +16142,22 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
15962
16142
|
return cleared;
|
|
15963
16143
|
}
|
|
15964
16144
|
async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
15965
|
-
let
|
|
16145
|
+
let record2;
|
|
15966
16146
|
try {
|
|
15967
|
-
|
|
16147
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
15968
16148
|
} catch {
|
|
15969
16149
|
return null;
|
|
15970
16150
|
}
|
|
15971
|
-
if (
|
|
16151
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15972
16152
|
let stale = false;
|
|
15973
16153
|
await ctx.database.write(async () => {
|
|
15974
|
-
if (
|
|
16154
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15975
16155
|
stale = true;
|
|
15976
16156
|
return;
|
|
15977
16157
|
}
|
|
15978
|
-
const currentUpdatedAt =
|
|
15979
|
-
const currentPublishedAt =
|
|
15980
|
-
await
|
|
16158
|
+
const currentUpdatedAt = record2.updatedAt.getTime();
|
|
16159
|
+
const currentPublishedAt = record2.publishedAt ?? null;
|
|
16160
|
+
await record2.update((r) => {
|
|
15981
16161
|
r._setRaw("visibility", opts.visibility);
|
|
15982
16162
|
if (opts.visibility === "private") {
|
|
15983
16163
|
r._setRaw("published_at", null);
|
|
@@ -15991,19 +16171,19 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
15991
16171
|
});
|
|
15992
16172
|
});
|
|
15993
16173
|
if (stale) return null;
|
|
15994
|
-
return vaultMemoryToStored(
|
|
16174
|
+
return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
15995
16175
|
}
|
|
15996
16176
|
async function deleteVaultMemoryOp(ctx, id) {
|
|
15997
16177
|
try {
|
|
15998
|
-
const
|
|
15999
|
-
if (
|
|
16178
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16179
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16000
16180
|
let stale = false;
|
|
16001
16181
|
await ctx.database.write(async () => {
|
|
16002
|
-
if (
|
|
16182
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
16003
16183
|
stale = true;
|
|
16004
16184
|
return;
|
|
16005
16185
|
}
|
|
16006
|
-
await
|
|
16186
|
+
await record2.update((r) => {
|
|
16007
16187
|
r._setRaw("is_deleted", true);
|
|
16008
16188
|
});
|
|
16009
16189
|
});
|
|
@@ -16022,8 +16202,9 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
16022
16202
|
async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
16023
16203
|
if (id === supersededById) return false;
|
|
16024
16204
|
try {
|
|
16025
|
-
const
|
|
16026
|
-
if (
|
|
16205
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16206
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16207
|
+
if (isKinded(record2)) return false;
|
|
16027
16208
|
let successor;
|
|
16028
16209
|
try {
|
|
16029
16210
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -16037,7 +16218,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
16037
16218
|
await ctx.database.write(async () => {
|
|
16038
16219
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
16039
16220
|
throw new Error("Memory source is no longer eligible");
|
|
16040
|
-
if (
|
|
16221
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
16041
16222
|
stale = true;
|
|
16042
16223
|
return;
|
|
16043
16224
|
}
|
|
@@ -16045,7 +16226,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
16045
16226
|
stale = true;
|
|
16046
16227
|
return;
|
|
16047
16228
|
}
|
|
16048
|
-
await
|
|
16229
|
+
await record2.update((r) => {
|
|
16049
16230
|
r._setRaw("superseded_by", supersededById);
|
|
16050
16231
|
r._setRaw("superseded_at", Date.now());
|
|
16051
16232
|
});
|
|
@@ -16064,7 +16245,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
16064
16245
|
const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
|
|
16065
16246
|
return mapInBatches(
|
|
16066
16247
|
results,
|
|
16067
|
-
(
|
|
16248
|
+
(record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
16068
16249
|
);
|
|
16069
16250
|
}
|
|
16070
16251
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
@@ -16206,17 +16387,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
16206
16387
|
}
|
|
16207
16388
|
}
|
|
16208
16389
|
const eligible = records.filter(
|
|
16209
|
-
(
|
|
16390
|
+
(record2) => !record2.isDeleted && isOwnedByCtxUser(ctx, record2) && !record2.topicsUserManaged
|
|
16210
16391
|
);
|
|
16211
|
-
const prepared = eligible.map((
|
|
16212
|
-
const originalUpdatedAt =
|
|
16213
|
-
return
|
|
16392
|
+
const prepared = eligible.map((record2) => {
|
|
16393
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
16394
|
+
return record2.prepareUpdate((r) => {
|
|
16214
16395
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
16215
16396
|
r._setRaw("topics_extracted_version", version);
|
|
16216
16397
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
16217
16398
|
});
|
|
16218
16399
|
});
|
|
16219
|
-
for (const
|
|
16400
|
+
for (const record2 of eligible) stamped.push(record2.id);
|
|
16220
16401
|
if (prepared.length > 0) await ctx.database.batch(...prepared);
|
|
16221
16402
|
});
|
|
16222
16403
|
}
|
|
@@ -16231,14 +16412,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
16231
16412
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
16232
16413
|
try {
|
|
16233
16414
|
await ctx.database.write(async (writer) => {
|
|
16234
|
-
let
|
|
16415
|
+
let record2;
|
|
16235
16416
|
try {
|
|
16236
|
-
|
|
16417
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16237
16418
|
} catch {
|
|
16238
16419
|
return;
|
|
16239
16420
|
}
|
|
16240
|
-
if (
|
|
16241
|
-
const topics = parseTopics(
|
|
16421
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
16422
|
+
const topics = parseTopics(record2.topics);
|
|
16242
16423
|
if (topics === null) return;
|
|
16243
16424
|
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
|
|
16244
16425
|
relinked.push(id);
|
|
@@ -16263,20 +16444,20 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
16263
16444
|
await ctx.database.write(async () => {
|
|
16264
16445
|
const writes = [];
|
|
16265
16446
|
for (const id of chunkIds) {
|
|
16266
|
-
let
|
|
16447
|
+
let record2;
|
|
16267
16448
|
try {
|
|
16268
|
-
|
|
16449
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16269
16450
|
} catch {
|
|
16270
16451
|
continue;
|
|
16271
16452
|
}
|
|
16272
|
-
if (
|
|
16273
|
-
if (parseTopics(
|
|
16453
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) continue;
|
|
16454
|
+
if (parseTopics(record2.topics) !== null) continue;
|
|
16274
16455
|
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb23.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
16275
16456
|
const entityIds = links.map((l) => String(l.entity_id));
|
|
16276
16457
|
if (entityIds.length === 0) continue;
|
|
16277
16458
|
const entities = await entityCtx.entityCollection.query(import_watermelondb23.Q.where("id", import_watermelondb23.Q.oneOf(entityIds))).fetch();
|
|
16278
16459
|
if (entities.length === 0) continue;
|
|
16279
|
-
const source =
|
|
16460
|
+
const source = record2.topicsUserManaged ? "user" : "auto";
|
|
16280
16461
|
const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
|
|
16281
16462
|
if (write) writes.push(write);
|
|
16282
16463
|
}
|
|
@@ -16294,7 +16475,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
16294
16475
|
if (records.length === 0) return 0;
|
|
16295
16476
|
await ctx.database.write(async () => {
|
|
16296
16477
|
const prepared = records.map(
|
|
16297
|
-
(
|
|
16478
|
+
(record2) => record2.prepareUpdate((r) => {
|
|
16298
16479
|
r._setRaw("is_deleted", true);
|
|
16299
16480
|
})
|
|
16300
16481
|
);
|
|
@@ -16324,7 +16505,10 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
16324
16505
|
}
|
|
16325
16506
|
async function getDecayCandidatesRawOp(ctx) {
|
|
16326
16507
|
assertVaultScopeForSweep(ctx);
|
|
16327
|
-
const results = await ctx.vaultMemoryCollection.query(
|
|
16508
|
+
const results = await ctx.vaultMemoryCollection.query(
|
|
16509
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
16510
|
+
import_watermelondb23.Q.where("kind", null)
|
|
16511
|
+
).unsafeFetchRaw();
|
|
16328
16512
|
return results.map((raw) => ({
|
|
16329
16513
|
uniqueId: raw.id,
|
|
16330
16514
|
factType: raw.fact_type ?? null,
|
|
@@ -16339,20 +16523,20 @@ async function getDecayCandidatesRawOp(ctx) {
|
|
|
16339
16523
|
}
|
|
16340
16524
|
async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
16341
16525
|
try {
|
|
16342
|
-
const
|
|
16343
|
-
if (
|
|
16526
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16527
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16344
16528
|
let stale = false;
|
|
16345
16529
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
16346
16530
|
await ctx.database.write(async () => {
|
|
16347
|
-
if (
|
|
16531
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
16348
16532
|
stale = true;
|
|
16349
16533
|
return;
|
|
16350
16534
|
}
|
|
16351
|
-
if (opts?.expectedUpdatedAt !== void 0 &&
|
|
16535
|
+
if (opts?.expectedUpdatedAt !== void 0 && record2.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record2.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
|
|
16352
16536
|
stale = true;
|
|
16353
16537
|
return;
|
|
16354
16538
|
}
|
|
16355
|
-
await
|
|
16539
|
+
await record2.update((r) => {
|
|
16356
16540
|
r._setRaw("archived_at", archivedAtValue);
|
|
16357
16541
|
});
|
|
16358
16542
|
});
|
|
@@ -16363,15 +16547,15 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
16363
16547
|
}
|
|
16364
16548
|
async function restoreVaultMemoryOp(ctx, id) {
|
|
16365
16549
|
try {
|
|
16366
|
-
const
|
|
16367
|
-
if (
|
|
16550
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16551
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16368
16552
|
let stale = false;
|
|
16369
16553
|
await ctx.database.write(async () => {
|
|
16370
|
-
if (
|
|
16554
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
16371
16555
|
stale = true;
|
|
16372
16556
|
return;
|
|
16373
16557
|
}
|
|
16374
|
-
await
|
|
16558
|
+
await record2.update((r) => {
|
|
16375
16559
|
r._setRaw("archived_at", null);
|
|
16376
16560
|
});
|
|
16377
16561
|
});
|
|
@@ -16382,17 +16566,17 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
16382
16566
|
}
|
|
16383
16567
|
async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
16384
16568
|
try {
|
|
16385
|
-
const
|
|
16386
|
-
if (
|
|
16569
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16570
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16387
16571
|
const now = opts.now ?? Date.now();
|
|
16388
16572
|
let stale = false;
|
|
16389
16573
|
await ctx.database.write(async () => {
|
|
16390
|
-
const archivedAt =
|
|
16391
|
-
if (
|
|
16574
|
+
const archivedAt = record2.archivedAt;
|
|
16575
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
16392
16576
|
stale = true;
|
|
16393
16577
|
return;
|
|
16394
16578
|
}
|
|
16395
|
-
await
|
|
16579
|
+
await record2.update((r) => {
|
|
16396
16580
|
r._setRaw("is_deleted", true);
|
|
16397
16581
|
});
|
|
16398
16582
|
});
|
|
@@ -16410,14 +16594,14 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
16410
16594
|
}
|
|
16411
16595
|
async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel, expected) {
|
|
16412
16596
|
try {
|
|
16413
|
-
const
|
|
16414
|
-
if (
|
|
16415
|
-
const readUpdatedAt =
|
|
16416
|
-
const readStoredContent =
|
|
16597
|
+
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16598
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16599
|
+
const readUpdatedAt = record2.updatedAt.getTime();
|
|
16600
|
+
const readStoredContent = record2._getRaw("content");
|
|
16417
16601
|
if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
|
|
16418
16602
|
if (expected?.content !== void 0) {
|
|
16419
16603
|
const current = await vaultMemoryToStored(
|
|
16420
|
-
|
|
16604
|
+
record2,
|
|
16421
16605
|
ctx.walletAddress,
|
|
16422
16606
|
ctx.signMessage,
|
|
16423
16607
|
ctx.embeddedWalletSigner
|
|
@@ -16426,11 +16610,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
16426
16610
|
}
|
|
16427
16611
|
let written = false;
|
|
16428
16612
|
await ctx.database.write(async () => {
|
|
16429
|
-
if (
|
|
16430
|
-
const originalUpdatedAt =
|
|
16431
|
-
if (originalUpdatedAt !== readUpdatedAt ||
|
|
16613
|
+
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
16614
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
16615
|
+
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
16432
16616
|
return;
|
|
16433
|
-
await
|
|
16617
|
+
await record2.update((r) => {
|
|
16434
16618
|
r._setRaw("embedding", embedding);
|
|
16435
16619
|
r._setRaw("embedding_model", embeddingModel);
|
|
16436
16620
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -16445,8 +16629,8 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
16445
16629
|
function normalizeForDedupe(content) {
|
|
16446
16630
|
return content.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
16447
16631
|
}
|
|
16448
|
-
async function findQuarantinedDuplicateOp(ctx, content,
|
|
16449
|
-
const wanted = [...new Set(
|
|
16632
|
+
async function findQuarantinedDuplicateOp(ctx, content, sourceIds2, where) {
|
|
16633
|
+
const wanted = [...new Set(sourceIds2)].sort().join("\0");
|
|
16450
16634
|
const target = normalizeForDedupe(content);
|
|
16451
16635
|
const rows = await ctx.vaultMemoryCollection.query(
|
|
16452
16636
|
import_watermelondb23.Q.where("trust_tier", "quarantined"),
|
|
@@ -16465,13 +16649,13 @@ async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
|
|
|
16465
16649
|
if (!Array.isArray(ids)) continue;
|
|
16466
16650
|
const key = [...new Set(ids.filter((id) => typeof id === "string"))].sort().join("\0");
|
|
16467
16651
|
if (key !== wanted) continue;
|
|
16468
|
-
const
|
|
16652
|
+
const stored2 = await vaultMemoryRawToStored(
|
|
16469
16653
|
raw,
|
|
16470
16654
|
ctx.walletAddress,
|
|
16471
16655
|
ctx.signMessage,
|
|
16472
16656
|
ctx.embeddedWalletSigner
|
|
16473
16657
|
);
|
|
16474
|
-
if (normalizeForDedupe(
|
|
16658
|
+
if (normalizeForDedupe(stored2.content) === target) return stored2.uniqueId;
|
|
16475
16659
|
}
|
|
16476
16660
|
return null;
|
|
16477
16661
|
}
|
|
@@ -16581,25 +16765,26 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
16581
16765
|
inserted = writable.length;
|
|
16582
16766
|
if (writable.length === 0) return;
|
|
16583
16767
|
const prepared = writable.map(
|
|
16584
|
-
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((
|
|
16585
|
-
|
|
16586
|
-
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16768
|
+
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record2) => {
|
|
16769
|
+
record2._raw.id = row.memoryId;
|
|
16770
|
+
record2._setRaw("content", content);
|
|
16771
|
+
record2._setRaw("scope", "shared");
|
|
16772
|
+
record2._setRaw("level", "matching");
|
|
16773
|
+
record2._setRaw("folder_id", null);
|
|
16774
|
+
record2._setRaw("user_id", ctx.userId ?? null);
|
|
16775
|
+
record2._setRaw("is_deleted", false);
|
|
16776
|
+
record2._setRaw("proof_count", 1);
|
|
16777
|
+
record2._setRaw("source", SOURCE_PHOTO);
|
|
16778
|
+
record2._setRaw(
|
|
16594
16779
|
"media",
|
|
16595
16780
|
row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
|
|
16596
16781
|
);
|
|
16597
|
-
|
|
16598
|
-
|
|
16782
|
+
record2._setRaw("visibility", "public");
|
|
16783
|
+
record2._setRaw("published_at", now);
|
|
16599
16784
|
if (row.eventTime) {
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16785
|
+
record2._setRaw("event_time_start", row.eventTime.start ?? null);
|
|
16786
|
+
record2._setRaw("event_time_end", row.eventTime.end ?? null);
|
|
16787
|
+
record2._setRaw("event_time_kind", row.eventTime.kind ?? null);
|
|
16603
16788
|
}
|
|
16604
16789
|
})
|
|
16605
16790
|
);
|
|
@@ -17421,11 +17606,11 @@ function folderToStored(folder) {
|
|
|
17421
17606
|
}
|
|
17422
17607
|
async function createVaultFolderOp(ctx, opts) {
|
|
17423
17608
|
const created = await ctx.database.write(async () => {
|
|
17424
|
-
return ctx.vaultFolderCollection.create((
|
|
17425
|
-
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17609
|
+
return ctx.vaultFolderCollection.create((record2) => {
|
|
17610
|
+
record2._setRaw("name", opts.name);
|
|
17611
|
+
record2._setRaw("scope", opts.scope ?? "private");
|
|
17612
|
+
record2._setRaw("is_system", opts.isSystem ?? false);
|
|
17613
|
+
record2._setRaw("is_deleted", false);
|
|
17429
17614
|
});
|
|
17430
17615
|
});
|
|
17431
17616
|
return folderToStored(created);
|
|
@@ -17436,14 +17621,14 @@ async function getAllVaultFoldersOp(ctx) {
|
|
|
17436
17621
|
}
|
|
17437
17622
|
async function updateVaultFolderOp(ctx, id, opts) {
|
|
17438
17623
|
try {
|
|
17439
|
-
const
|
|
17440
|
-
if (
|
|
17441
|
-
const scopeChanged = opts.scope !== void 0 && opts.scope !==
|
|
17624
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
17625
|
+
if (record2.isDeleted) return null;
|
|
17626
|
+
const scopeChanged = opts.scope !== void 0 && opts.scope !== record2.scope;
|
|
17442
17627
|
const updated = await ctx.database.write(async () => {
|
|
17443
17628
|
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(import_watermelondb30.Q.where("folder_id", id), import_watermelondb30.Q.where("is_deleted", false)).fetch() : [];
|
|
17444
17629
|
const updates = [];
|
|
17445
17630
|
updates.push(
|
|
17446
|
-
|
|
17631
|
+
record2.prepareUpdate((r) => {
|
|
17447
17632
|
if (opts.name !== void 0) r._setRaw("name", opts.name);
|
|
17448
17633
|
if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
|
|
17449
17634
|
})
|
|
@@ -17451,6 +17636,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
17451
17636
|
for (const memory of memories) {
|
|
17452
17637
|
updates.push(
|
|
17453
17638
|
memory.prepareUpdate((r) => {
|
|
17639
|
+
r._setRaw("level", levelForScopeChange(r, opts.scope));
|
|
17454
17640
|
r._setRaw("scope", opts.scope);
|
|
17455
17641
|
})
|
|
17456
17642
|
);
|
|
@@ -17465,17 +17651,18 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
17465
17651
|
}
|
|
17466
17652
|
async function deleteVaultFolderOp(ctx, id) {
|
|
17467
17653
|
try {
|
|
17468
|
-
const
|
|
17469
|
-
if (
|
|
17654
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
17655
|
+
if (record2.isDeleted) return false;
|
|
17470
17656
|
await ctx.database.write(async () => {
|
|
17471
17657
|
const memories = await ctx.vaultMemoryCollection.query(import_watermelondb30.Q.where("folder_id", id), import_watermelondb30.Q.where("is_deleted", false)).fetch();
|
|
17472
17658
|
const preparedMemories = memories.map(
|
|
17473
17659
|
(memory) => memory.prepareUpdate((r) => {
|
|
17474
17660
|
r._setRaw("folder_id", null);
|
|
17661
|
+
r._setRaw("level", levelForScopeChange(r, "private"));
|
|
17475
17662
|
r._setRaw("scope", "private");
|
|
17476
17663
|
})
|
|
17477
17664
|
);
|
|
17478
|
-
const preparedFolder =
|
|
17665
|
+
const preparedFolder = record2.prepareUpdate((r) => {
|
|
17479
17666
|
r._setRaw("is_deleted", true);
|
|
17480
17667
|
});
|
|
17481
17668
|
await ctx.database.batch(...preparedMemories, preparedFolder);
|
|
@@ -17508,6 +17695,7 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
17508
17695
|
const prepared = memories.map(
|
|
17509
17696
|
(memory) => memory.prepareUpdate((r) => {
|
|
17510
17697
|
r._setRaw("folder_id", folderId);
|
|
17698
|
+
r._setRaw("level", levelForScopeChange(r, targetScope));
|
|
17511
17699
|
r._setRaw("scope", targetScope);
|
|
17512
17700
|
})
|
|
17513
17701
|
);
|
|
@@ -17521,11 +17709,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
17521
17709
|
}
|
|
17522
17710
|
async function updateVaultFolderContextOp(ctx, id, context) {
|
|
17523
17711
|
try {
|
|
17524
|
-
const
|
|
17525
|
-
if (
|
|
17712
|
+
const record2 = await ctx.vaultFolderCollection.find(id);
|
|
17713
|
+
if (record2.isDeleted) return null;
|
|
17526
17714
|
const updated = await ctx.database.write(async () => {
|
|
17527
17715
|
await ctx.database.batch(
|
|
17528
|
-
|
|
17716
|
+
record2.prepareUpdate((r) => {
|
|
17529
17717
|
r._setRaw("context", context);
|
|
17530
17718
|
})
|
|
17531
17719
|
);
|
|
@@ -19606,7 +19794,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
19606
19794
|
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
19607
19795
|
let subEmbeddings;
|
|
19608
19796
|
try {
|
|
19609
|
-
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
19797
|
+
subEmbeddings = prepared.facetEmbeddings ?? await generateEmbeddings(facetQueries, embeddingOptions);
|
|
19610
19798
|
} catch (err) {
|
|
19611
19799
|
getLogger().warn(
|
|
19612
19800
|
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
@@ -19792,6 +19980,35 @@ var DEFAULT_SCOPE = "private";
|
|
|
19792
19980
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
19793
19981
|
var DEFAULT_CONSOLIDATE_TOP_K = 20;
|
|
19794
19982
|
async function retain(content, ctx, options = {}) {
|
|
19983
|
+
return retainWithPersistence(
|
|
19984
|
+
content,
|
|
19985
|
+
{
|
|
19986
|
+
embeddingOptions: ctx.embeddingOptions,
|
|
19987
|
+
vaultCache: ctx.vaultCache,
|
|
19988
|
+
persistence: {
|
|
19989
|
+
prepare: (query, searchOptions) => prepareVaultCandidates(
|
|
19990
|
+
query,
|
|
19991
|
+
ctx.vaultCtx,
|
|
19992
|
+
ctx.embeddingOptions,
|
|
19993
|
+
ctx.vaultCache,
|
|
19994
|
+
searchOptions
|
|
19995
|
+
),
|
|
19996
|
+
get: (id) => getVaultMemoryOp(ctx.vaultCtx, id),
|
|
19997
|
+
tombstones: (_embedding, _model, scope, folderId) => getAllVaultMemoriesOp(ctx.vaultCtx, {
|
|
19998
|
+
includeDeleted: true,
|
|
19999
|
+
scopes: [scope],
|
|
20000
|
+
...folderId !== void 0 && { folderId }
|
|
20001
|
+
}),
|
|
20002
|
+
create: (input) => createVaultMemoryOp(ctx.vaultCtx, input),
|
|
20003
|
+
update: (id, patch) => updateVaultMemoryOp(ctx.vaultCtx, id, patch),
|
|
20004
|
+
supersede: (id, successor) => supersedeVaultMemoryOp(ctx.vaultCtx, id, successor),
|
|
20005
|
+
createSuperseding: (input, target) => createSupersedingMemoryOp(ctx.vaultCtx, input, target)
|
|
20006
|
+
}
|
|
20007
|
+
},
|
|
20008
|
+
options
|
|
20009
|
+
);
|
|
20010
|
+
}
|
|
20011
|
+
async function retainWithPersistence(content, ctx, options = {}) {
|
|
19795
20012
|
const trimmed = content.trim();
|
|
19796
20013
|
if (trimmed.length === 0) {
|
|
19797
20014
|
throw new Error("retain: content cannot be empty");
|
|
@@ -19804,19 +20021,14 @@ async function retain(content, ctx, options = {}) {
|
|
|
19804
20021
|
let supersedeContent;
|
|
19805
20022
|
let prepared;
|
|
19806
20023
|
if (enableAutoMerge) {
|
|
19807
|
-
prepared = await
|
|
19808
|
-
|
|
19809
|
-
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
{
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
scopes: [resolvedScope],
|
|
19816
|
-
includeArchived: true,
|
|
19817
|
-
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
19818
|
-
}
|
|
19819
|
-
);
|
|
20024
|
+
prepared = await ctx.persistence.prepare(trimmed, {
|
|
20025
|
+
limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
|
|
20026
|
+
useFusion: false,
|
|
20027
|
+
scopes: [resolvedScope],
|
|
20028
|
+
includeArchived: true,
|
|
20029
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
20030
|
+
});
|
|
20031
|
+
prepared = withoutKindedRows(prepared);
|
|
19820
20032
|
if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
|
|
19821
20033
|
throw new Error(
|
|
19822
20034
|
"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 +20059,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19847
20059
|
);
|
|
19848
20060
|
if (matches.length > 0) {
|
|
19849
20061
|
const targetId = matches[0].uniqueId;
|
|
19850
|
-
const existing = await
|
|
20062
|
+
const existing = await ctx.persistence.get(targetId);
|
|
19851
20063
|
if (existing && !existing.supersededBy) {
|
|
19852
20064
|
const mergedSourceIds = unionStrings(
|
|
19853
20065
|
existing.sourceChunkIds ?? [],
|
|
@@ -19856,8 +20068,9 @@ async function retain(content, ctx, options = {}) {
|
|
|
19856
20068
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
19857
20069
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
19858
20070
|
const resurrect = resurrectFields(existing);
|
|
19859
|
-
const updated = await
|
|
20071
|
+
const updated = await ctx.persistence.update(targetId, {
|
|
19860
20072
|
content: existing.content,
|
|
20073
|
+
freeFormOnly: true,
|
|
19861
20074
|
proofCountIncrement: 1,
|
|
19862
20075
|
observationSourceIds: options.sourceChunkIds,
|
|
19863
20076
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -19883,7 +20096,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
19883
20096
|
}
|
|
19884
20097
|
const contentToWrite = supersedeContent ?? trimmed;
|
|
19885
20098
|
const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
|
|
19886
|
-
const
|
|
20099
|
+
const generatedEmbedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
20100
|
+
const embedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
19887
20101
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19888
20102
|
if (options.respectTombstones) {
|
|
19889
20103
|
const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
@@ -19923,8 +20137,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19923
20137
|
};
|
|
19924
20138
|
if (supersedeTargetIds.length > 0) {
|
|
19925
20139
|
const [primaryTargetId, ...restTargetIds] = supersedeTargetIds;
|
|
19926
|
-
const { created: created2, retired } = await
|
|
19927
|
-
ctx.vaultCtx,
|
|
20140
|
+
const { created: created2, retired } = await ctx.persistence.createSuperseding(
|
|
19928
20141
|
createOpts,
|
|
19929
20142
|
primaryTargetId
|
|
19930
20143
|
);
|
|
@@ -19940,11 +20153,11 @@ async function retain(content, ctx, options = {}) {
|
|
|
19940
20153
|
for (const staleId of restTargetIds) {
|
|
19941
20154
|
let ok = false;
|
|
19942
20155
|
try {
|
|
19943
|
-
ok = await
|
|
20156
|
+
ok = await ctx.persistence.supersede(staleId, created2.uniqueId) === true;
|
|
19944
20157
|
} catch {
|
|
19945
20158
|
}
|
|
19946
20159
|
if (ok) continue;
|
|
19947
|
-
const stillLive = await
|
|
20160
|
+
const stillLive = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(staleId) : ctx.persistence.get(staleId)).catch(() => null);
|
|
19948
20161
|
if (stillLive && !stillLive.supersededBy) liveLeftovers.push(staleId);
|
|
19949
20162
|
}
|
|
19950
20163
|
if (liveLeftovers.length > 0) {
|
|
@@ -19971,7 +20184,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
19971
20184
|
`supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
|
|
19972
20185
|
);
|
|
19973
20186
|
}
|
|
19974
|
-
const created = await
|
|
20187
|
+
const created = await ctx.persistence.create(createOpts);
|
|
19975
20188
|
cacheRowVector(
|
|
19976
20189
|
ctx.vaultCache,
|
|
19977
20190
|
created.uniqueId,
|
|
@@ -19986,15 +20199,22 @@ async function retain(content, ctx, options = {}) {
|
|
|
19986
20199
|
...consolidationDecidedCreate && { consolidation: "create" }
|
|
19987
20200
|
};
|
|
19988
20201
|
}
|
|
20202
|
+
function withoutKindedRows(prepared) {
|
|
20203
|
+
const kinded = new Set(
|
|
20204
|
+
prepared.memories.filter((m) => m.kind !== null && m.kind !== void 0).map((m) => m.uniqueId)
|
|
20205
|
+
);
|
|
20206
|
+
if (kinded.size === 0) return prepared;
|
|
20207
|
+
return {
|
|
20208
|
+
...prepared,
|
|
20209
|
+
memories: prepared.memories.filter((m) => !kinded.has(m.uniqueId)),
|
|
20210
|
+
embeddedItems: prepared.embeddedItems.filter((item) => !kinded.has(item.id))
|
|
20211
|
+
};
|
|
20212
|
+
}
|
|
19989
20213
|
function unionStrings(a, b) {
|
|
19990
20214
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
19991
20215
|
}
|
|
19992
20216
|
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
|
-
});
|
|
20217
|
+
const rows = await ctx.persistence.tombstones(embedding, embeddingModel, scope, opts.folderId);
|
|
19998
20218
|
let bestId = null;
|
|
19999
20219
|
let bestSim = opts.threshold;
|
|
20000
20220
|
for (const row of rows) {
|
|
@@ -20061,7 +20281,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20061
20281
|
if (requestedIds.length === 0) return null;
|
|
20062
20282
|
const valid = [];
|
|
20063
20283
|
for (const id of requestedIds) {
|
|
20064
|
-
const existing = await
|
|
20284
|
+
const existing = await ctx.persistence.get(id);
|
|
20065
20285
|
if (existing && !existing.supersededBy) valid.push(id);
|
|
20066
20286
|
}
|
|
20067
20287
|
if (valid.length === 0) {
|
|
@@ -20073,7 +20293,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20073
20293
|
return { supersede: valid, content: decision.content };
|
|
20074
20294
|
}
|
|
20075
20295
|
if (decision.action === "noop" && decision.targetId) {
|
|
20076
|
-
const existing = await
|
|
20296
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
20077
20297
|
if (!existing || existing.supersededBy) {
|
|
20078
20298
|
return abandonToRace(
|
|
20079
20299
|
options,
|
|
@@ -20087,8 +20307,9 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20087
20307
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
20088
20308
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
20089
20309
|
const resurrect = resurrectFields(existing);
|
|
20090
|
-
const updated = await
|
|
20310
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
20091
20311
|
content: existing.content,
|
|
20312
|
+
freeFormOnly: true,
|
|
20092
20313
|
proofCountIncrement: 1,
|
|
20093
20314
|
observationSourceIds: options.sourceChunkIds,
|
|
20094
20315
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -20115,7 +20336,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20115
20336
|
};
|
|
20116
20337
|
}
|
|
20117
20338
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
20118
|
-
const existing = await
|
|
20339
|
+
const existing = await ctx.persistence.get(decision.targetId);
|
|
20119
20340
|
if (!existing || existing.supersededBy) {
|
|
20120
20341
|
return abandonToRace(
|
|
20121
20342
|
options,
|
|
@@ -20126,13 +20347,15 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20126
20347
|
existing.sourceChunkIds ?? [],
|
|
20127
20348
|
options.sourceChunkIds ?? []
|
|
20128
20349
|
);
|
|
20129
|
-
const
|
|
20350
|
+
const generatedEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
|
|
20351
|
+
const newEmbedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
|
|
20130
20352
|
const consolidatedModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
20131
20353
|
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
20132
20354
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
20133
20355
|
const resurrect = resurrectFields(existing);
|
|
20134
|
-
const updated = await
|
|
20356
|
+
const updated = await ctx.persistence.update(decision.targetId, {
|
|
20135
20357
|
content: decision.content,
|
|
20358
|
+
freeFormOnly: true,
|
|
20136
20359
|
proofCountIncrement: 1,
|
|
20137
20360
|
observationSourceIds: options.sourceChunkIds,
|
|
20138
20361
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -20175,8 +20398,8 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20175
20398
|
return null;
|
|
20176
20399
|
}
|
|
20177
20400
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
20178
|
-
const stillExists = await
|
|
20179
|
-
if (stillExists) {
|
|
20401
|
+
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
20402
|
+
if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
|
|
20180
20403
|
throw new Error(`retain: merge into memory ${targetId} failed to persist`);
|
|
20181
20404
|
}
|
|
20182
20405
|
}
|
|
@@ -20692,9 +20915,9 @@ function createAutoExtractor(options) {
|
|
|
20692
20915
|
const persistCursor = (conversationId, messages, advancedToId, contiguous) => {
|
|
20693
20916
|
if (!cursorStore || conversationId === void 0 || !contiguous) return;
|
|
20694
20917
|
try {
|
|
20695
|
-
const
|
|
20696
|
-
if (
|
|
20697
|
-
const storedIdx = messages.findIndex((m) => m.id ===
|
|
20918
|
+
const stored2 = cursorStore.get(conversationId);
|
|
20919
|
+
if (stored2 && stored2 !== advancedToId) {
|
|
20920
|
+
const storedIdx = messages.findIndex((m) => m.id === stored2);
|
|
20698
20921
|
const newIdx = messages.findIndex((m) => m.id === advancedToId);
|
|
20699
20922
|
if (storedIdx !== -1 && newIdx !== -1 && storedIdx >= newIdx) return;
|
|
20700
20923
|
}
|
|
@@ -21674,7 +21897,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21674
21897
|
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
21675
21898
|
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
21676
21899
|
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;
|
|
21900
|
+
const laneRan = types.includes("fact") && (!!ctx.factSource || !!ctx.vaultCtx && !!ctx.vaultCache) || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
|
|
21678
21901
|
const scores = admitted.map((m) => m.score);
|
|
21679
21902
|
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
21680
21903
|
const diagnostics = {
|
|
@@ -21716,7 +21939,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21716
21939
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
21717
21940
|
}
|
|
21718
21941
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
21719
|
-
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
21942
|
+
const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
|
|
21720
21943
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
21721
21944
|
const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
|
|
21722
21945
|
const prepStart = nowMs2();
|
|
@@ -21746,7 +21969,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21746
21969
|
safeLane(
|
|
21747
21970
|
"graph",
|
|
21748
21971
|
() => graphLaneFailed = true,
|
|
21749
|
-
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
21972
|
+
() => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
21750
21973
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
21751
21974
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
21752
21975
|
...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
|
|
@@ -21757,13 +21980,13 @@ async function recall(query, ctx, options = {}) {
|
|
|
21757
21980
|
wantsTemporal ? safeLane(
|
|
21758
21981
|
"temporal",
|
|
21759
21982
|
() => temporalLaneFailed = true,
|
|
21760
|
-
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
21983
|
+
() => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
21761
21984
|
) : Promise.resolve([])
|
|
21762
21985
|
]);
|
|
21763
21986
|
prepMs = nowMs2() - prepStart;
|
|
21764
21987
|
graphLaneCount = entityRanking.length;
|
|
21765
21988
|
temporalLaneCount = temporalRanking.length;
|
|
21766
|
-
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
21989
|
+
if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
|
|
21767
21990
|
const factStart = nowMs2();
|
|
21768
21991
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
21769
21992
|
factFloor = vaultMinScore;
|
|
@@ -21779,50 +22002,50 @@ async function recall(query, ctx, options = {}) {
|
|
|
21779
22002
|
rankedOnCosine: factRankedOnCosine,
|
|
21780
22003
|
decryptLast: factDecryptLast,
|
|
21781
22004
|
rowsDecrypted: factRowsDecrypted
|
|
21782
|
-
} = await searchVaultMemoriesWithSize(
|
|
21783
|
-
|
|
22005
|
+
} = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
|
|
22006
|
+
searchQuery,
|
|
21784
22007
|
ctx.vaultCtx,
|
|
21785
22008
|
ctx.embeddingOptions,
|
|
21786
22009
|
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
|
-
);
|
|
22010
|
+
searchOptions
|
|
22011
|
+
)))(query, {
|
|
22012
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
22013
|
+
minSimilarity: vaultMinScore,
|
|
22014
|
+
useFusion: true,
|
|
22015
|
+
rerank: flags.rerank,
|
|
22016
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
22017
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
22018
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
22019
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
22020
|
+
},
|
|
22021
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
22022
|
+
...options.recency && { recency: options.recency },
|
|
22023
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
22024
|
+
...options.supersessionBoost !== void 0 && {
|
|
22025
|
+
supersessionBoost: options.supersessionBoost
|
|
22026
|
+
},
|
|
22027
|
+
...options.supersessionWindow !== void 0 && {
|
|
22028
|
+
supersessionWindow: options.supersessionWindow
|
|
22029
|
+
},
|
|
22030
|
+
...options.proofCountAlpha !== void 0 && {
|
|
22031
|
+
proofCountAlpha: options.proofCountAlpha
|
|
22032
|
+
},
|
|
22033
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
22034
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
22035
|
+
},
|
|
22036
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
22037
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
22038
|
+
...subQueries && { subQueries },
|
|
22039
|
+
...options.scopes && { scopes: options.scopes },
|
|
22040
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
22041
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
22042
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
22043
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
22044
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
22045
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
22046
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
22047
|
+
queryEmbedTotalTimeoutMs
|
|
22048
|
+
});
|
|
21826
22049
|
factResults.push(
|
|
21827
22050
|
...dedupeBy(
|
|
21828
22051
|
results,
|
|
@@ -22635,26 +22858,26 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
22635
22858
|
};
|
|
22636
22859
|
const inputs = [];
|
|
22637
22860
|
for (const id of new Set(memoryIds)) {
|
|
22638
|
-
let
|
|
22861
|
+
let record2;
|
|
22639
22862
|
try {
|
|
22640
|
-
|
|
22863
|
+
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
22641
22864
|
} catch (err) {
|
|
22642
22865
|
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
22643
22866
|
skip(id, "not-found");
|
|
22644
22867
|
continue;
|
|
22645
22868
|
}
|
|
22646
|
-
if (
|
|
22869
|
+
if (record2.isDeleted || ctx.userId !== void 0 && record2.userId !== ctx.userId || record2.topicsUserManaged) {
|
|
22647
22870
|
skip(id, "excluded");
|
|
22648
22871
|
continue;
|
|
22649
22872
|
}
|
|
22650
22873
|
try {
|
|
22651
|
-
const
|
|
22652
|
-
|
|
22874
|
+
const stored2 = await vaultMemoryToStored(
|
|
22875
|
+
record2,
|
|
22653
22876
|
ctx.walletAddress,
|
|
22654
22877
|
ctx.signMessage,
|
|
22655
22878
|
ctx.embeddedWalletSigner
|
|
22656
22879
|
);
|
|
22657
|
-
inputs.push({ id, content:
|
|
22880
|
+
inputs.push({ id, content: stored2.content });
|
|
22658
22881
|
} catch (err) {
|
|
22659
22882
|
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
22660
22883
|
skip(id, "unreadable");
|
|
@@ -22839,6 +23062,781 @@ function createLocalMemoryStore(options) {
|
|
|
22839
23062
|
};
|
|
22840
23063
|
}
|
|
22841
23064
|
|
|
23065
|
+
// src/lib/memory/store/remotePersistence.ts
|
|
23066
|
+
var RemoteMemoryError = class extends Error {
|
|
23067
|
+
constructor(message, status, code) {
|
|
23068
|
+
super(message);
|
|
23069
|
+
this.status = status;
|
|
23070
|
+
this.code = code;
|
|
23071
|
+
this.name = "RemoteMemoryError";
|
|
23072
|
+
}
|
|
23073
|
+
};
|
|
23074
|
+
var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
|
|
23075
|
+
var memoryFields = {
|
|
23076
|
+
memory_id: true,
|
|
23077
|
+
content: true,
|
|
23078
|
+
scope: true,
|
|
23079
|
+
created_at: true,
|
|
23080
|
+
updated_at: true,
|
|
23081
|
+
is_deleted: true,
|
|
23082
|
+
embedding: true,
|
|
23083
|
+
embedding_model: true,
|
|
23084
|
+
kind: true,
|
|
23085
|
+
kind_value: true,
|
|
23086
|
+
level: true,
|
|
23087
|
+
folder_id: true,
|
|
23088
|
+
source_chunk_ids: true,
|
|
23089
|
+
proof_count: true,
|
|
23090
|
+
source: true,
|
|
23091
|
+
event_time_start: true,
|
|
23092
|
+
event_time_end: true,
|
|
23093
|
+
event_time_kind: true,
|
|
23094
|
+
topics_user_managed: true,
|
|
23095
|
+
topics: true,
|
|
23096
|
+
topics_updated_at: true,
|
|
23097
|
+
media: true,
|
|
23098
|
+
topics_extracted_at: true,
|
|
23099
|
+
topics_extracted_version: true,
|
|
23100
|
+
superseded_by: true,
|
|
23101
|
+
superseded_at: true,
|
|
23102
|
+
last_observed_at: true,
|
|
23103
|
+
fact_type: true,
|
|
23104
|
+
archived_at: true,
|
|
23105
|
+
trust_tier: true,
|
|
23106
|
+
visibility: true,
|
|
23107
|
+
twin_opt_in: true,
|
|
23108
|
+
published_at: true,
|
|
23109
|
+
geohash: true
|
|
23110
|
+
};
|
|
23111
|
+
var candidateListLimits = [
|
|
23112
|
+
["scopes", 20],
|
|
23113
|
+
["fact_types", 20],
|
|
23114
|
+
["memory_ids", 1e3],
|
|
23115
|
+
["force_ids", 100]
|
|
23116
|
+
];
|
|
23117
|
+
function record(value) {
|
|
23118
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23119
|
+
}
|
|
23120
|
+
function memoryRecord(value) {
|
|
23121
|
+
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))) {
|
|
23122
|
+
throw new Error("Invalid nearby private-memory response");
|
|
23123
|
+
}
|
|
23124
|
+
return value;
|
|
23125
|
+
}
|
|
23126
|
+
async function createRemoteMemoryPersistence(options) {
|
|
23127
|
+
const base = new URL(options.baseUrl);
|
|
23128
|
+
if (!/^https?:$/.test(base.protocol) || base.username || base.password || base.search || base.hash) {
|
|
23129
|
+
throw new Error(
|
|
23130
|
+
"baseUrl must be an HTTP(S) origin or base path without credentials, query or fragment"
|
|
23131
|
+
);
|
|
23132
|
+
}
|
|
23133
|
+
if (!options.keyId || options.keyId.length > 256)
|
|
23134
|
+
throw new Error("A canonical keyId is required");
|
|
23135
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
23136
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
23137
|
+
throw new Error("timeoutMs must be a positive number");
|
|
23138
|
+
const root = base.href.replace(/\/$/, "") + "/api/private-memories";
|
|
23139
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
23140
|
+
const request = async (path, init = {}, signal) => {
|
|
23141
|
+
const controller = new AbortController();
|
|
23142
|
+
let timedOut = false;
|
|
23143
|
+
const timer = setTimeout(() => {
|
|
23144
|
+
timedOut = true;
|
|
23145
|
+
controller.abort();
|
|
23146
|
+
}, timeoutMs);
|
|
23147
|
+
const forwardAbort = () => controller.abort(signal?.reason);
|
|
23148
|
+
if (signal?.aborted) forwardAbort();
|
|
23149
|
+
else signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
23150
|
+
let rejectAborted;
|
|
23151
|
+
const aborted = new Promise((_, reject) => {
|
|
23152
|
+
rejectAborted = () => reject(
|
|
23153
|
+
controller.signal.reason instanceof Error ? controller.signal.reason : new Error("Nearby request aborted")
|
|
23154
|
+
);
|
|
23155
|
+
if (controller.signal.aborted) rejectAborted();
|
|
23156
|
+
else controller.signal.addEventListener("abort", rejectAborted, { once: true });
|
|
23157
|
+
});
|
|
23158
|
+
aborted.catch(() => void 0);
|
|
23159
|
+
try {
|
|
23160
|
+
const token = await Promise.race([options.getToken(), aborted]);
|
|
23161
|
+
if (controller.signal.aborted) await aborted;
|
|
23162
|
+
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
23163
|
+
const response = await fetcher(root + path, {
|
|
23164
|
+
...init,
|
|
23165
|
+
headers: {
|
|
23166
|
+
Authorization: `Bearer ${token}`,
|
|
23167
|
+
...init.body ? { "Content-Type": "application/json" } : {}
|
|
23168
|
+
},
|
|
23169
|
+
redirect: "error",
|
|
23170
|
+
signal: controller.signal
|
|
23171
|
+
});
|
|
23172
|
+
if (!response.ok) {
|
|
23173
|
+
const body = await response.json().catch(() => null);
|
|
23174
|
+
throw new RemoteMemoryError(
|
|
23175
|
+
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
23176
|
+
response.status,
|
|
23177
|
+
record(body) && typeof body.code === "string" ? body.code : void 0
|
|
23178
|
+
);
|
|
23179
|
+
}
|
|
23180
|
+
return await response.json();
|
|
23181
|
+
} catch (error) {
|
|
23182
|
+
if (timedOut) throw new RemoteMemoryError("Nearby request timed out", 408, "timeout");
|
|
23183
|
+
throw error;
|
|
23184
|
+
} finally {
|
|
23185
|
+
clearTimeout(timer);
|
|
23186
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
23187
|
+
if (rejectAborted) controller.signal.removeEventListener("abort", rejectAborted);
|
|
23188
|
+
}
|
|
23189
|
+
};
|
|
23190
|
+
const account = await request("/account", {}, options.signal);
|
|
23191
|
+
if (!record(account) || account.state !== "active") {
|
|
23192
|
+
throw new RemoteMemoryError(
|
|
23193
|
+
"Complete and verify migration before using remote memories",
|
|
23194
|
+
409,
|
|
23195
|
+
"memory_not_active"
|
|
23196
|
+
);
|
|
23197
|
+
}
|
|
23198
|
+
if (account.key_id !== options.keyId) {
|
|
23199
|
+
throw new RemoteMemoryError(
|
|
23200
|
+
"The canonical memory key does not match this account",
|
|
23201
|
+
409,
|
|
23202
|
+
"key_mismatch"
|
|
23203
|
+
);
|
|
23204
|
+
}
|
|
23205
|
+
const snapshots = /* @__PURE__ */ new WeakMap();
|
|
23206
|
+
const decode = async (value) => {
|
|
23207
|
+
const item = memoryRecord(value);
|
|
23208
|
+
const decrypt = async (ciphertext) => {
|
|
23209
|
+
if (!ciphertextPattern.test(ciphertext))
|
|
23210
|
+
throw new Error("Nearby returned unencrypted memory content");
|
|
23211
|
+
const plaintext = await options.decrypt(ciphertext);
|
|
23212
|
+
if (plaintext === ciphertext) throw new Error("Memory decryption failed");
|
|
23213
|
+
return plaintext;
|
|
23214
|
+
};
|
|
23215
|
+
const decoded = {
|
|
23216
|
+
...item,
|
|
23217
|
+
memory: {
|
|
23218
|
+
...item.memory,
|
|
23219
|
+
content: await decrypt(item.memory.content),
|
|
23220
|
+
...item.memory.kind_value !== void 0 && {
|
|
23221
|
+
kind_value: await decrypt(item.memory.kind_value)
|
|
23222
|
+
}
|
|
23223
|
+
}
|
|
23224
|
+
};
|
|
23225
|
+
return remember(decoded, item);
|
|
23226
|
+
};
|
|
23227
|
+
const remember = (decoded, item) => {
|
|
23228
|
+
snapshots.set(decoded, {
|
|
23229
|
+
id: item.memory.memory_id,
|
|
23230
|
+
version: item.version,
|
|
23231
|
+
content: decoded.memory.content,
|
|
23232
|
+
kindValue: decoded.memory.kind_value,
|
|
23233
|
+
encryptedContent: item.memory.content,
|
|
23234
|
+
encryptedKindValue: item.memory.kind_value
|
|
23235
|
+
});
|
|
23236
|
+
return decoded;
|
|
23237
|
+
};
|
|
23238
|
+
const decodeAll = async (values) => {
|
|
23239
|
+
const records = values.map(memoryRecord);
|
|
23240
|
+
const settled = await Promise.allSettled(records.map(decode));
|
|
23241
|
+
const items = [];
|
|
23242
|
+
const failed = [];
|
|
23243
|
+
settled.forEach((result, i) => {
|
|
23244
|
+
if (result.status === "fulfilled") items.push(result.value);
|
|
23245
|
+
else
|
|
23246
|
+
failed.push({
|
|
23247
|
+
memory_id: records[i].memory.memory_id,
|
|
23248
|
+
version: records[i].version,
|
|
23249
|
+
error: result.reason instanceof Error ? result.reason : new Error(String(result.reason))
|
|
23250
|
+
});
|
|
23251
|
+
});
|
|
23252
|
+
return { items, failed };
|
|
23253
|
+
};
|
|
23254
|
+
const decodeCommitted = async (value, write) => {
|
|
23255
|
+
const item = memoryRecord(value);
|
|
23256
|
+
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)
|
|
23257
|
+
return decode(item);
|
|
23258
|
+
return remember(
|
|
23259
|
+
{
|
|
23260
|
+
...item,
|
|
23261
|
+
memory: {
|
|
23262
|
+
...item.memory,
|
|
23263
|
+
content: write.content,
|
|
23264
|
+
...write.kindValue !== void 0 && { kind_value: write.kindValue }
|
|
23265
|
+
}
|
|
23266
|
+
},
|
|
23267
|
+
item
|
|
23268
|
+
);
|
|
23269
|
+
};
|
|
23270
|
+
const encryptField2 = async (plaintext) => {
|
|
23271
|
+
const ciphertext = await options.encrypt(plaintext);
|
|
23272
|
+
if (ciphertext === plaintext || !ciphertextPattern.test(ciphertext))
|
|
23273
|
+
throw new Error("Field encryption must return SDK ciphertext; refusing to upload plaintext");
|
|
23274
|
+
return ciphertext;
|
|
23275
|
+
};
|
|
23276
|
+
const memoryPath = (id) => {
|
|
23277
|
+
if (!id || id.length > 128) throw new Error("memory_id must be 1\u2013128 characters");
|
|
23278
|
+
return "/memories/" + encodeURIComponent(id);
|
|
23279
|
+
};
|
|
23280
|
+
const prepareWrite = async (memory, expectedVersion, signal) => {
|
|
23281
|
+
const unknown = Object.keys(memory).filter(
|
|
23282
|
+
(key) => !Object.prototype.hasOwnProperty.call(memoryFields, key)
|
|
23283
|
+
);
|
|
23284
|
+
if (unknown.length) {
|
|
23285
|
+
throw new RemoteMemoryError(
|
|
23286
|
+
`Unknown private-memory fields (${unknown.join(", ")}); refusing to forward them`,
|
|
23287
|
+
400,
|
|
23288
|
+
"unknown_field"
|
|
23289
|
+
);
|
|
23290
|
+
}
|
|
23291
|
+
memory = { ...memory, ...memory.embedding && { embedding: [...memory.embedding] } };
|
|
23292
|
+
const path = memoryPath(memory.memory_id);
|
|
23293
|
+
const snapshot = typeof expectedVersion === "number" ? void 0 : snapshots.get(expectedVersion);
|
|
23294
|
+
if (typeof expectedVersion !== "number" && (!snapshot || snapshot.id !== memory.memory_id || snapshot.version !== expectedVersion.version))
|
|
23295
|
+
throw new Error(
|
|
23296
|
+
"Expected snapshot must be an unmodified version from this persistence instance"
|
|
23297
|
+
);
|
|
23298
|
+
expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
|
|
23299
|
+
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
23300
|
+
throw new Error("expectedVersion must be a nonnegative integer");
|
|
23301
|
+
const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
|
|
23302
|
+
let existing;
|
|
23303
|
+
if (expectedVersion !== 0 && !snapshot) {
|
|
23304
|
+
try {
|
|
23305
|
+
existing = memoryRecord(await request(path, {}, signal));
|
|
23306
|
+
} catch (error) {
|
|
23307
|
+
if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
|
|
23308
|
+
throw error;
|
|
23309
|
+
}
|
|
23310
|
+
}
|
|
23311
|
+
if (existing && existing.version !== expectedVersion) throw conflict();
|
|
23312
|
+
const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
|
|
23313
|
+
const content = (snapshot?.content ?? decoded?.memory.content) === memory.content ? snapshot?.encryptedContent ?? existing.memory.content : await encryptField2(memory.content);
|
|
23314
|
+
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);
|
|
23315
|
+
return {
|
|
23316
|
+
body: {
|
|
23317
|
+
expected_version: expectedVersion,
|
|
23318
|
+
memory: { ...memory, content, ...kindValue !== void 0 && { kind_value: kindValue } }
|
|
23319
|
+
},
|
|
23320
|
+
content: memory.content,
|
|
23321
|
+
kindValue: memory.kind_value
|
|
23322
|
+
};
|
|
23323
|
+
};
|
|
23324
|
+
const fetchCandidates = async (embedding, candidateOptions, withCounts) => {
|
|
23325
|
+
const limit = candidateOptions.limit ?? 100;
|
|
23326
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
23327
|
+
throw new Error("Candidate limit must be 1\u2013100");
|
|
23328
|
+
for (const [key, max] of candidateListLimits) {
|
|
23329
|
+
const values = candidateOptions[key];
|
|
23330
|
+
if (values && values.length > max)
|
|
23331
|
+
throw new Error(`Candidate ${key} accepts at most ${max} entries (got ${values.length})`);
|
|
23332
|
+
}
|
|
23333
|
+
const result = await request(
|
|
23334
|
+
"/candidates",
|
|
23335
|
+
{
|
|
23336
|
+
method: "POST",
|
|
23337
|
+
body: JSON.stringify({
|
|
23338
|
+
embedding,
|
|
23339
|
+
limit,
|
|
23340
|
+
force_ids: candidateOptions.force_ids ?? [],
|
|
23341
|
+
...withCounts && { with_counts: true },
|
|
23342
|
+
...Object.fromEntries(
|
|
23343
|
+
[
|
|
23344
|
+
"scopes",
|
|
23345
|
+
"memory_ids",
|
|
23346
|
+
"embedding_model",
|
|
23347
|
+
"strict_model",
|
|
23348
|
+
"include_deleted",
|
|
23349
|
+
"deleted_only"
|
|
23350
|
+
].filter(
|
|
23351
|
+
(key) => candidateOptions[key] !== void 0
|
|
23352
|
+
).map((key) => [key, candidateOptions[key]])
|
|
23353
|
+
),
|
|
23354
|
+
...candidateOptions.fact_types !== void 0 && {
|
|
23355
|
+
fact_types: candidateOptions.fact_types
|
|
23356
|
+
},
|
|
23357
|
+
...candidateOptions.include_archived !== void 0 && {
|
|
23358
|
+
include_archived: candidateOptions.include_archived
|
|
23359
|
+
},
|
|
23360
|
+
...candidateOptions.include_quarantined !== void 0 && {
|
|
23361
|
+
include_quarantined: candidateOptions.include_quarantined
|
|
23362
|
+
},
|
|
23363
|
+
...candidateOptions.include_superseded !== void 0 && {
|
|
23364
|
+
include_superseded: candidateOptions.include_superseded
|
|
23365
|
+
}
|
|
23366
|
+
})
|
|
23367
|
+
},
|
|
23368
|
+
candidateOptions.signal
|
|
23369
|
+
);
|
|
23370
|
+
if (!record(result) || !Array.isArray(result.items))
|
|
23371
|
+
throw new Error("Invalid nearby candidate response");
|
|
23372
|
+
return result;
|
|
23373
|
+
};
|
|
23374
|
+
const candidateSet = async (embedding, candidateOptions = {}) => {
|
|
23375
|
+
const result = await fetchCandidates(embedding, candidateOptions, true);
|
|
23376
|
+
if (!Number.isSafeInteger(result.total_count) || result.total_count < 0 || !Number.isSafeInteger(result.unavailable_count) || result.unavailable_count < 0)
|
|
23377
|
+
throw new Error("Invalid nearby candidate response");
|
|
23378
|
+
return {
|
|
23379
|
+
...await decodeAll(result.items),
|
|
23380
|
+
total_count: result.total_count,
|
|
23381
|
+
unavailable_count: result.unavailable_count
|
|
23382
|
+
};
|
|
23383
|
+
};
|
|
23384
|
+
return {
|
|
23385
|
+
get: async (id, signal) => {
|
|
23386
|
+
try {
|
|
23387
|
+
return await decode(await request(memoryPath(id), {}, signal));
|
|
23388
|
+
} catch (error) {
|
|
23389
|
+
if (error instanceof RemoteMemoryError && error.status === 404) return null;
|
|
23390
|
+
throw error;
|
|
23391
|
+
}
|
|
23392
|
+
},
|
|
23393
|
+
list: async (listOptions = {}) => {
|
|
23394
|
+
const { signal, ...query } = listOptions;
|
|
23395
|
+
if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200)) {
|
|
23396
|
+
throw new Error("Page limit must be 1\u2013200");
|
|
23397
|
+
}
|
|
23398
|
+
const params = new URLSearchParams();
|
|
23399
|
+
for (const key of [
|
|
23400
|
+
"cursor",
|
|
23401
|
+
"limit",
|
|
23402
|
+
"include_deleted",
|
|
23403
|
+
"include_archived",
|
|
23404
|
+
"include_quarantined",
|
|
23405
|
+
"include_superseded",
|
|
23406
|
+
"include_embeddings"
|
|
23407
|
+
]) {
|
|
23408
|
+
if (query[key] !== void 0) params.set(key, String(query[key]));
|
|
23409
|
+
}
|
|
23410
|
+
const page = await request("/memories?" + params.toString(), {}, signal);
|
|
23411
|
+
if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
|
|
23412
|
+
throw new Error("Invalid nearby private-memory page");
|
|
23413
|
+
}
|
|
23414
|
+
return {
|
|
23415
|
+
...await decodeAll(page.items),
|
|
23416
|
+
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
|
|
23417
|
+
};
|
|
23418
|
+
},
|
|
23419
|
+
put: async (memory, expectedVersion, signal) => {
|
|
23420
|
+
const write = await prepareWrite(memory, expectedVersion, signal);
|
|
23421
|
+
return decodeCommitted(
|
|
23422
|
+
await request(
|
|
23423
|
+
memoryPath(write.body.memory.memory_id),
|
|
23424
|
+
{
|
|
23425
|
+
method: "PUT",
|
|
23426
|
+
body: JSON.stringify({ key_id: options.keyId, ...write.body })
|
|
23427
|
+
},
|
|
23428
|
+
signal
|
|
23429
|
+
),
|
|
23430
|
+
write
|
|
23431
|
+
);
|
|
23432
|
+
},
|
|
23433
|
+
putMany: async (writes, signal) => {
|
|
23434
|
+
if (writes.length < 1 || writes.length > 50 || new Set(writes.map((w) => w.memory.memory_id)).size !== writes.length)
|
|
23435
|
+
throw new Error("Batch must contain 1\u201350 distinct memory ids");
|
|
23436
|
+
const prepared = await Promise.all(
|
|
23437
|
+
writes.map((w) => prepareWrite(w.memory, w.expectedVersion, signal))
|
|
23438
|
+
);
|
|
23439
|
+
const result = await request(
|
|
23440
|
+
"/memories/batch",
|
|
23441
|
+
{
|
|
23442
|
+
method: "POST",
|
|
23443
|
+
body: JSON.stringify({ key_id: options.keyId, writes: prepared.map((w) => w.body) })
|
|
23444
|
+
},
|
|
23445
|
+
signal
|
|
23446
|
+
);
|
|
23447
|
+
if (!record(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
|
|
23448
|
+
throw new Error("Invalid nearby batch response");
|
|
23449
|
+
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
23450
|
+
},
|
|
23451
|
+
candidateSet,
|
|
23452
|
+
candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
|
|
23453
|
+
};
|
|
23454
|
+
}
|
|
23455
|
+
|
|
23456
|
+
// src/lib/memory/store/remotePipeline.ts
|
|
23457
|
+
var import_uuid5 = require("uuid");
|
|
23458
|
+
init_logger();
|
|
23459
|
+
function storedVector(vector) {
|
|
23460
|
+
if (!Array.isArray(vector) || vector.length !== 1536 && vector.length !== 4096 || vector.some((v) => !Number.isFinite(v)))
|
|
23461
|
+
throw new Error("Remote memories require a finite 1536/4096-dimensional vector");
|
|
23462
|
+
const out = vector.slice(0, 1536);
|
|
23463
|
+
const norm = Math.sqrt(out.reduce((sum, v) => sum + v * v, 0));
|
|
23464
|
+
if (!norm) throw new Error("Remote query/content vector has no direction after MRL truncation");
|
|
23465
|
+
return out.map((v) => v / norm);
|
|
23466
|
+
}
|
|
23467
|
+
function sourceIds(value) {
|
|
23468
|
+
if (!value) return [];
|
|
23469
|
+
try {
|
|
23470
|
+
const parsed = JSON.parse(value);
|
|
23471
|
+
return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string") : [];
|
|
23472
|
+
} catch {
|
|
23473
|
+
return [];
|
|
23474
|
+
}
|
|
23475
|
+
}
|
|
23476
|
+
function isMemoryLevel(value) {
|
|
23477
|
+
return MEMORY_LEVELS.includes(value);
|
|
23478
|
+
}
|
|
23479
|
+
function stored(row) {
|
|
23480
|
+
return {
|
|
23481
|
+
uniqueId: row.memory_id,
|
|
23482
|
+
content: row.content,
|
|
23483
|
+
scope: row.scope,
|
|
23484
|
+
folderId: row.folder_id ?? null,
|
|
23485
|
+
userId: null,
|
|
23486
|
+
kind: row.kind ?? null,
|
|
23487
|
+
kindValue: row.kind_value ?? null,
|
|
23488
|
+
...isMemoryLevel(row.level) && { level: row.level },
|
|
23489
|
+
embedding: row.embedding ? JSON.stringify(row.embedding) : null,
|
|
23490
|
+
embeddingModel: row.embedding_model ?? null,
|
|
23491
|
+
sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
|
|
23492
|
+
proofCount: row.proof_count ?? null,
|
|
23493
|
+
source: row.source ?? null,
|
|
23494
|
+
media: parseMedia(row.media),
|
|
23495
|
+
eventTimeStart: row.event_time_start ?? null,
|
|
23496
|
+
eventTimeEnd: row.event_time_end ?? null,
|
|
23497
|
+
eventTimeKind: row.event_time_kind ?? null,
|
|
23498
|
+
topicsUserManaged: row.topics_user_managed ?? false,
|
|
23499
|
+
topics: parseTopics(row.topics),
|
|
23500
|
+
topicsUpdatedAt: row.topics_updated_at ?? null,
|
|
23501
|
+
topicsExtractedAt: row.topics_extracted_at ?? null,
|
|
23502
|
+
topicsExtractedVersion: row.topics_extracted_version ?? null,
|
|
23503
|
+
supersededBy: row.superseded_by ?? null,
|
|
23504
|
+
supersededAt: row.superseded_at ?? null,
|
|
23505
|
+
lastObservedAt: row.last_observed_at ?? null,
|
|
23506
|
+
factType: row.fact_type ?? null,
|
|
23507
|
+
archivedAt: row.archived_at ?? null,
|
|
23508
|
+
trustTier: row.trust_tier ?? null,
|
|
23509
|
+
visibility: row.visibility === "public" ? "public" : "private",
|
|
23510
|
+
twinOptIn: row.twin_opt_in ?? false,
|
|
23511
|
+
publishedAt: row.published_at ?? null,
|
|
23512
|
+
geohash: row.geohash ?? null,
|
|
23513
|
+
createdAt: new Date(row.created_at),
|
|
23514
|
+
updatedAt: new Date(row.updated_at),
|
|
23515
|
+
isDeleted: row.is_deleted
|
|
23516
|
+
};
|
|
23517
|
+
}
|
|
23518
|
+
function createRemoteMemoryPipeline(options) {
|
|
23519
|
+
const { persistence, embeddingOptions } = options;
|
|
23520
|
+
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
23521
|
+
const operation = (mode) => {
|
|
23522
|
+
const rejectUndecryptable = (failed) => {
|
|
23523
|
+
if (!failed.length) return;
|
|
23524
|
+
if (mode === "retain")
|
|
23525
|
+
throw new Error(
|
|
23526
|
+
`Remote memories could not decrypt ${failed.length} candidate row(s); refusing to retain until they are repaired`
|
|
23527
|
+
);
|
|
23528
|
+
getLogger().warn(
|
|
23529
|
+
`[memory/remote] Skipping ${failed.length} undecryptable candidate row(s)`,
|
|
23530
|
+
failed.map((failure) => failure.memory_id)
|
|
23531
|
+
);
|
|
23532
|
+
};
|
|
23533
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
23534
|
+
const remember = (items) => {
|
|
23535
|
+
items.forEach((item) => snapshots.set(item.memory.memory_id, item));
|
|
23536
|
+
return items.map((item) => stored(item.memory));
|
|
23537
|
+
};
|
|
23538
|
+
const get = async (id) => {
|
|
23539
|
+
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
23540
|
+
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
23541
|
+
snapshots.set(id, snapshot);
|
|
23542
|
+
return stored(snapshot.memory);
|
|
23543
|
+
};
|
|
23544
|
+
const prepare = async (query, search = {}) => {
|
|
23545
|
+
if (search.folderId !== void 0)
|
|
23546
|
+
throw new Error("Remote memories do not support folder filters");
|
|
23547
|
+
const facets = normalizeSubQueries(search.subQueries);
|
|
23548
|
+
const facetQueries = facets.length >= 2 ? facets : [];
|
|
23549
|
+
const start = Date.now();
|
|
23550
|
+
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
23551
|
+
const embed = (texts) => generateEmbeddings(texts, {
|
|
23552
|
+
...embeddingOptions,
|
|
23553
|
+
totalTimeoutMs: budgetMs
|
|
23554
|
+
});
|
|
23555
|
+
const embedFacets = async () => {
|
|
23556
|
+
if (!facetQueries.length) return [];
|
|
23557
|
+
try {
|
|
23558
|
+
const vectors2 = await embed(facetQueries);
|
|
23559
|
+
if (vectors2.length !== facetQueries.length)
|
|
23560
|
+
throw new Error("Incomplete facet embeddings");
|
|
23561
|
+
return vectors2.map(storedVector);
|
|
23562
|
+
} catch (error) {
|
|
23563
|
+
getLogger().warn(
|
|
23564
|
+
"[memory/remote] Facet embeddings unavailable; using primary query",
|
|
23565
|
+
error
|
|
23566
|
+
);
|
|
23567
|
+
return [];
|
|
23568
|
+
}
|
|
23569
|
+
};
|
|
23570
|
+
const [primary, facetEmbeddings] = await Promise.all([
|
|
23571
|
+
search.queryEmbedding ?? embed([query]).then((vectors2) => vectors2[0]),
|
|
23572
|
+
embedFacets()
|
|
23573
|
+
]);
|
|
23574
|
+
const queryEmbedding = storedVector(primary);
|
|
23575
|
+
const queryEmbedMs = Date.now() - start;
|
|
23576
|
+
const graph = search.entityRanking ?? [];
|
|
23577
|
+
const temporal = search.temporalRanking ?? [];
|
|
23578
|
+
const forced = /* @__PURE__ */ new Set();
|
|
23579
|
+
for (let i = 0; i < Math.max(graph.length, temporal.length) && forced.size < 100; i++) {
|
|
23580
|
+
if (graph[i] !== void 0) forced.add(graph[i]);
|
|
23581
|
+
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
23582
|
+
}
|
|
23583
|
+
const forceIds = [...forced];
|
|
23584
|
+
const windowOptions = (i, signal) => ({
|
|
23585
|
+
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
23586
|
+
force_ids: i === 0 ? forceIds : [],
|
|
23587
|
+
...search.scopes && { scopes: search.scopes },
|
|
23588
|
+
...search.factTypes && { fact_types: search.factTypes },
|
|
23589
|
+
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
23590
|
+
include_archived: search.includeArchived,
|
|
23591
|
+
embedding_model: model,
|
|
23592
|
+
...signal && { signal }
|
|
23593
|
+
});
|
|
23594
|
+
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
23595
|
+
let windows;
|
|
23596
|
+
if (mode === "retain") {
|
|
23597
|
+
windows = await Promise.all(
|
|
23598
|
+
vectors.map((embedding, i) => persistence.candidateSet(embedding, windowOptions(i)))
|
|
23599
|
+
);
|
|
23600
|
+
} else {
|
|
23601
|
+
const deadline = new AbortController();
|
|
23602
|
+
const timer = setTimeout(
|
|
23603
|
+
() => deadline.abort(
|
|
23604
|
+
new RemoteMemoryError("Remote recall exceeded its query budget", 408, "timeout")
|
|
23605
|
+
),
|
|
23606
|
+
Math.max(0, start + budgetMs - Date.now())
|
|
23607
|
+
);
|
|
23608
|
+
try {
|
|
23609
|
+
windows = await Promise.all(
|
|
23610
|
+
vectors.map(
|
|
23611
|
+
(embedding, i) => persistence.candidates(embedding, windowOptions(i, deadline.signal))
|
|
23612
|
+
)
|
|
23613
|
+
);
|
|
23614
|
+
} finally {
|
|
23615
|
+
clearTimeout(timer);
|
|
23616
|
+
}
|
|
23617
|
+
}
|
|
23618
|
+
rejectUndecryptable([
|
|
23619
|
+
...new Map(
|
|
23620
|
+
windows.flatMap((window2) => window2.failed).map((failure) => [failure.memory_id, failure])
|
|
23621
|
+
).values()
|
|
23622
|
+
]);
|
|
23623
|
+
const items = [
|
|
23624
|
+
...new Map(
|
|
23625
|
+
windows.flatMap((window2) => window2.items).map((item) => [item.memory.memory_id, item])
|
|
23626
|
+
).values()
|
|
23627
|
+
];
|
|
23628
|
+
const memories = remember(items);
|
|
23629
|
+
return {
|
|
23630
|
+
memories,
|
|
23631
|
+
embeddedItems: memories.map((memory) => ({
|
|
23632
|
+
id: memory.uniqueId,
|
|
23633
|
+
content: memory.content,
|
|
23634
|
+
embedding: JSON.parse(memory.embedding ?? "[]"),
|
|
23635
|
+
createdAt: memory.createdAt,
|
|
23636
|
+
updatedAt: memory.updatedAt,
|
|
23637
|
+
proofCount: memory.proofCount,
|
|
23638
|
+
lastObservedAt: memory.lastObservedAt,
|
|
23639
|
+
eventTimeStart: memory.eventTimeStart,
|
|
23640
|
+
eventTimeEnd: memory.eventTimeEnd,
|
|
23641
|
+
eventTimeKind: memory.eventTimeKind === "point" || memory.eventTimeKind === "range" || memory.eventTimeKind === "ongoing" ? memory.eventTimeKind : null,
|
|
23642
|
+
factType: memory.factType,
|
|
23643
|
+
sourceChunkIds: memory.sourceChunkIds
|
|
23644
|
+
})),
|
|
23645
|
+
queryEmbedding,
|
|
23646
|
+
facetEmbeddings,
|
|
23647
|
+
vaultSize: Math.max(windows[0].total_count ?? 0, items.length),
|
|
23648
|
+
embeddingFailure: windows.some((window2) => (window2.unavailable_count ?? 0) > 0),
|
|
23649
|
+
embeddingsUnavailable: (windows[0].total_count ?? items.length) > 0 && !memories.some((memory) => memory.embedding),
|
|
23650
|
+
decryptLast: true,
|
|
23651
|
+
rowsDecrypted: items.length,
|
|
23652
|
+
queryEmbedMs,
|
|
23653
|
+
rowsEmbedded: 0
|
|
23654
|
+
};
|
|
23655
|
+
};
|
|
23656
|
+
const createRow = (input) => {
|
|
23657
|
+
if (input.folderId !== void 0 && input.folderId !== null)
|
|
23658
|
+
throw new Error("Remote memories do not support folders");
|
|
23659
|
+
const now = Date.now();
|
|
23660
|
+
return {
|
|
23661
|
+
memory_id: (0, import_uuid5.v7)(),
|
|
23662
|
+
content: input.content,
|
|
23663
|
+
scope: input.scope ?? "private",
|
|
23664
|
+
created_at: now,
|
|
23665
|
+
updated_at: now,
|
|
23666
|
+
is_deleted: false,
|
|
23667
|
+
...input.embedding !== void 0 && {
|
|
23668
|
+
embedding: storedVector(JSON.parse(input.embedding)),
|
|
23669
|
+
embedding_model: input.embeddingModel
|
|
23670
|
+
},
|
|
23671
|
+
source_chunk_ids: JSON.stringify(input.sourceChunkIds ?? []),
|
|
23672
|
+
proof_count: input.proofCount ?? 1,
|
|
23673
|
+
source: input.source ?? "manual",
|
|
23674
|
+
...input.eventTime && {
|
|
23675
|
+
event_time_start: input.eventTime.start ?? void 0,
|
|
23676
|
+
event_time_end: input.eventTime.end ?? void 0,
|
|
23677
|
+
event_time_kind: input.eventTime.kind ?? void 0
|
|
23678
|
+
},
|
|
23679
|
+
fact_type: input.factType,
|
|
23680
|
+
trust_tier: normalizeTrustTier(input.trustTier) ?? void 0,
|
|
23681
|
+
geohash: input.geohash,
|
|
23682
|
+
visibility: "private",
|
|
23683
|
+
twin_opt_in: false
|
|
23684
|
+
};
|
|
23685
|
+
};
|
|
23686
|
+
const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
|
|
23687
|
+
const port = {
|
|
23688
|
+
prepare,
|
|
23689
|
+
get,
|
|
23690
|
+
getFresh: async (id) => {
|
|
23691
|
+
const current = await persistence.get(id);
|
|
23692
|
+
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
23693
|
+
},
|
|
23694
|
+
tombstones: async (embedding, embeddingModel, scope, folderId) => {
|
|
23695
|
+
if (folderId !== void 0) throw new Error("Remote memories do not support folders");
|
|
23696
|
+
const window2 = await persistence.candidateSet(storedVector(embedding), {
|
|
23697
|
+
limit: 1,
|
|
23698
|
+
scopes: [scope],
|
|
23699
|
+
embedding_model: embeddingModel,
|
|
23700
|
+
strict_model: true,
|
|
23701
|
+
include_deleted: true,
|
|
23702
|
+
deleted_only: true
|
|
23703
|
+
});
|
|
23704
|
+
rejectUndecryptable(window2.failed);
|
|
23705
|
+
return remember(window2.items);
|
|
23706
|
+
},
|
|
23707
|
+
create: (input) => write(createRow(input), 0),
|
|
23708
|
+
update: async (id, patch) => {
|
|
23709
|
+
const existing = await get(id);
|
|
23710
|
+
if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
|
|
23711
|
+
return null;
|
|
23712
|
+
const snapshot = snapshots.get(id);
|
|
23713
|
+
const memory = {
|
|
23714
|
+
...snapshot.memory,
|
|
23715
|
+
content: patch.content,
|
|
23716
|
+
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
|
|
23717
|
+
};
|
|
23718
|
+
if (patch.scope !== void 0) memory.scope = patch.scope;
|
|
23719
|
+
if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
|
|
23720
|
+
delete memory.embedding;
|
|
23721
|
+
delete memory.embedding_model;
|
|
23722
|
+
}
|
|
23723
|
+
if (patch.embedding !== void 0) {
|
|
23724
|
+
memory.embedding = patch.embedding === null ? [] : storedVector(JSON.parse(patch.embedding));
|
|
23725
|
+
memory.embedding_model = patch.embeddingModel ?? void 0;
|
|
23726
|
+
}
|
|
23727
|
+
const observed = sourceIds(memory.source_chunk_ids);
|
|
23728
|
+
const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
|
|
23729
|
+
if (patch.sourceChunkIds !== void 0)
|
|
23730
|
+
memory.source_chunk_ids = JSON.stringify(
|
|
23731
|
+
patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
|
|
23732
|
+
);
|
|
23733
|
+
if (!replay) {
|
|
23734
|
+
if (patch.proofCountIncrement !== void 0)
|
|
23735
|
+
memory.proof_count = (memory.proof_count ?? 1) + patch.proofCountIncrement;
|
|
23736
|
+
else if (patch.proofCount !== void 0) memory.proof_count = patch.proofCount;
|
|
23737
|
+
if (patch.lastObservedAt !== void 0) memory.last_observed_at = patch.lastObservedAt;
|
|
23738
|
+
}
|
|
23739
|
+
if (patch.source !== void 0) memory.source = patch.source;
|
|
23740
|
+
if (patch.factType !== void 0) memory.fact_type = patch.factType;
|
|
23741
|
+
if (patch.trustTier !== void 0)
|
|
23742
|
+
memory.trust_tier = normalizeTrustTier(patch.trustTier) ?? void 0;
|
|
23743
|
+
if (patch.topicsUserManaged !== void 0)
|
|
23744
|
+
memory.topics_user_managed = patch.topicsUserManaged;
|
|
23745
|
+
if (patch.eventTime !== void 0) {
|
|
23746
|
+
memory.event_time_start = patch.eventTime.start ?? void 0;
|
|
23747
|
+
memory.event_time_end = patch.eventTime.end ?? void 0;
|
|
23748
|
+
memory.event_time_kind = patch.eventTime.kind ?? void 0;
|
|
23749
|
+
}
|
|
23750
|
+
if (patch.restore) memory.archived_at = void 0;
|
|
23751
|
+
return write(memory, snapshot);
|
|
23752
|
+
},
|
|
23753
|
+
supersede: async (id, successor) => {
|
|
23754
|
+
const [target, newer] = await Promise.all([get(id), get(successor)]);
|
|
23755
|
+
if (!target || !newer || id === successor) return false;
|
|
23756
|
+
const old = snapshots.get(id);
|
|
23757
|
+
const next = snapshots.get(successor);
|
|
23758
|
+
remember(
|
|
23759
|
+
await persistence.putMany([
|
|
23760
|
+
{
|
|
23761
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
23762
|
+
expectedVersion: old
|
|
23763
|
+
},
|
|
23764
|
+
{ memory: next.memory, expectedVersion: next }
|
|
23765
|
+
])
|
|
23766
|
+
);
|
|
23767
|
+
return true;
|
|
23768
|
+
},
|
|
23769
|
+
createSuperseding: async (input, targetId) => {
|
|
23770
|
+
const target = await get(targetId);
|
|
23771
|
+
if (!target) return { created: null, retired: false };
|
|
23772
|
+
const snapshot = snapshots.get(targetId);
|
|
23773
|
+
const successor = createRow(input);
|
|
23774
|
+
const rows = remember(
|
|
23775
|
+
await persistence.putMany([
|
|
23776
|
+
{ memory: successor, expectedVersion: 0 },
|
|
23777
|
+
{
|
|
23778
|
+
memory: {
|
|
23779
|
+
...snapshot.memory,
|
|
23780
|
+
superseded_by: successor.memory_id,
|
|
23781
|
+
superseded_at: Date.now()
|
|
23782
|
+
},
|
|
23783
|
+
expectedVersion: snapshot
|
|
23784
|
+
}
|
|
23785
|
+
])
|
|
23786
|
+
);
|
|
23787
|
+
return { created: rows[0], retired: true };
|
|
23788
|
+
}
|
|
23789
|
+
};
|
|
23790
|
+
return { prepare, port };
|
|
23791
|
+
};
|
|
23792
|
+
return {
|
|
23793
|
+
recall: async (query, recallOptions = {}) => {
|
|
23794
|
+
const { prepare } = operation("recall");
|
|
23795
|
+
return recall(
|
|
23796
|
+
query,
|
|
23797
|
+
{
|
|
23798
|
+
embeddingOptions,
|
|
23799
|
+
factSource: {
|
|
23800
|
+
graphRanking: options.graphRanking,
|
|
23801
|
+
temporalRanking: options.temporalRanking,
|
|
23802
|
+
search: async (text12, searchOptions) => {
|
|
23803
|
+
const prepared = await prepare(text12, searchOptions);
|
|
23804
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
23805
|
+
text12,
|
|
23806
|
+
prepared,
|
|
23807
|
+
embeddingOptions,
|
|
23808
|
+
searchOptions
|
|
23809
|
+
);
|
|
23810
|
+
return {
|
|
23811
|
+
...ranked,
|
|
23812
|
+
rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
|
|
23813
|
+
decryptLast: true,
|
|
23814
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
23815
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
23816
|
+
rowsEmbedded: 0
|
|
23817
|
+
};
|
|
23818
|
+
}
|
|
23819
|
+
}
|
|
23820
|
+
},
|
|
23821
|
+
{ ...recallOptions, types: ["fact"] }
|
|
23822
|
+
);
|
|
23823
|
+
},
|
|
23824
|
+
retain: async (content, retainOptions) => {
|
|
23825
|
+
const { port } = operation("retain");
|
|
23826
|
+
return retainWithPersistence(
|
|
23827
|
+
content,
|
|
23828
|
+
{
|
|
23829
|
+
persistence: port,
|
|
23830
|
+
embeddingOptions,
|
|
23831
|
+
vaultCache: /* @__PURE__ */ new Map(),
|
|
23832
|
+
normalizeEmbedding: storedVector
|
|
23833
|
+
},
|
|
23834
|
+
retainOptions
|
|
23835
|
+
);
|
|
23836
|
+
}
|
|
23837
|
+
};
|
|
23838
|
+
}
|
|
23839
|
+
|
|
22842
23840
|
// src/lib/memory/synthesizeProfile.ts
|
|
22843
23841
|
init_internalFlowMarker();
|
|
22844
23842
|
init_logger();
|
|
@@ -29098,7 +30096,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
29098
30096
|
const recordName = `backup_${filename.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
29099
30097
|
const arrayBuffer = await content.arrayBuffer();
|
|
29100
30098
|
const base64Data = uint8ArrayToBase64(new Uint8Array(arrayBuffer));
|
|
29101
|
-
const
|
|
30099
|
+
const record2 = {
|
|
29102
30100
|
recordType: RECORD_TYPE,
|
|
29103
30101
|
recordName,
|
|
29104
30102
|
fields: {
|
|
@@ -29108,7 +30106,7 @@ async function uploadFileToICloud(filename, content) {
|
|
|
29108
30106
|
contentType: { value: content.type || "application/json" }
|
|
29109
30107
|
}
|
|
29110
30108
|
};
|
|
29111
|
-
const response = await database.saveRecords(
|
|
30109
|
+
const response = await database.saveRecords(record2);
|
|
29112
30110
|
if (!response.records || response.records.length === 0) {
|
|
29113
30111
|
throw new Error("Failed to upload file to iCloud");
|
|
29114
30112
|
}
|
|
@@ -29134,11 +30132,11 @@ async function listICloudFiles() {
|
|
|
29134
30132
|
while (response.continuationMarker) {
|
|
29135
30133
|
break;
|
|
29136
30134
|
}
|
|
29137
|
-
const files = allRecords.map((
|
|
29138
|
-
recordName:
|
|
29139
|
-
filename:
|
|
29140
|
-
modifiedAt: new Date(
|
|
29141
|
-
size: typeof
|
|
30135
|
+
const files = allRecords.map((record2) => ({
|
|
30136
|
+
recordName: record2.recordName,
|
|
30137
|
+
filename: record2.fields.filename?.value ?? "",
|
|
30138
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
30139
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
29142
30140
|
}));
|
|
29143
30141
|
return files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
29144
30142
|
}
|
|
@@ -29151,8 +30149,8 @@ async function downloadICloudFile(recordName) {
|
|
|
29151
30149
|
if (!response.records || response.records.length === 0) {
|
|
29152
30150
|
throw new Error(`File not found: ${recordName}`);
|
|
29153
30151
|
}
|
|
29154
|
-
const
|
|
29155
|
-
const dataField =
|
|
30152
|
+
const record2 = response.records[0];
|
|
30153
|
+
const dataField = record2.fields.data?.value;
|
|
29156
30154
|
if (!dataField) {
|
|
29157
30155
|
throw new Error("No data in record");
|
|
29158
30156
|
}
|
|
@@ -29186,12 +30184,12 @@ async function findICloudFile(filename) {
|
|
|
29186
30184
|
if (!response.records || response.records.length === 0) {
|
|
29187
30185
|
return null;
|
|
29188
30186
|
}
|
|
29189
|
-
const
|
|
30187
|
+
const record2 = response.records[0];
|
|
29190
30188
|
return {
|
|
29191
|
-
recordName:
|
|
29192
|
-
filename:
|
|
29193
|
-
modifiedAt: new Date(
|
|
29194
|
-
size: typeof
|
|
30189
|
+
recordName: record2.recordName,
|
|
30190
|
+
filename: record2.fields.filename?.value ?? "",
|
|
30191
|
+
modifiedAt: new Date(record2.modified?.timestamp ?? Date.now()),
|
|
30192
|
+
size: typeof record2.fields.data?.value === "object" && record2.fields.data?.value !== null ? record2.fields.data.value.size : 0
|
|
29195
30193
|
};
|
|
29196
30194
|
}
|
|
29197
30195
|
|
|
@@ -29346,8 +30344,8 @@ async function getStoredTokenData5(provider, walletAddress) {
|
|
|
29346
30344
|
return null;
|
|
29347
30345
|
}
|
|
29348
30346
|
}
|
|
29349
|
-
async function readTokenRow(
|
|
29350
|
-
if (
|
|
30347
|
+
async function readTokenRow(stored2, provider, walletAddress) {
|
|
30348
|
+
if (stored2.startsWith(ENCRYPTED_PREFIX6)) {
|
|
29351
30349
|
if (!walletAddress) {
|
|
29352
30350
|
getLogger().warn(
|
|
29353
30351
|
`Encrypted OAuth token found for ${provider} but no wallet address provided`
|
|
@@ -29355,7 +30353,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
29355
30353
|
return null;
|
|
29356
30354
|
}
|
|
29357
30355
|
try {
|
|
29358
|
-
const encryptedData =
|
|
30356
|
+
const encryptedData = stored2.slice(ENCRYPTED_PREFIX6.length);
|
|
29359
30357
|
let decryptedJson;
|
|
29360
30358
|
try {
|
|
29361
30359
|
decryptedJson = await decryptData(encryptedData, walletAddress);
|
|
@@ -29370,7 +30368,7 @@ async function readTokenRow(stored, provider, walletAddress) {
|
|
|
29370
30368
|
return null;
|
|
29371
30369
|
}
|
|
29372
30370
|
}
|
|
29373
|
-
return parsePlaintextToken(
|
|
30371
|
+
return parsePlaintextToken(stored2, walletAddress);
|
|
29374
30372
|
}
|
|
29375
30373
|
async function storeTokenData5(provider, data, walletAddress) {
|
|
29376
30374
|
if (typeof window === "undefined") return;
|
|
@@ -29446,8 +30444,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
29446
30444
|
const keys = [scopedKey, legacyKey];
|
|
29447
30445
|
const isEncrypted2 = (value) => !!value && value.startsWith(ENCRYPTED_PREFIX6);
|
|
29448
30446
|
const plaintextAt = (key) => {
|
|
29449
|
-
const
|
|
29450
|
-
return
|
|
30447
|
+
const stored2 = sessionStorage.getItem(key) ?? localStorage.getItem(key);
|
|
30448
|
+
return stored2 && !isEncrypted2(stored2) ? stored2 : null;
|
|
29451
30449
|
};
|
|
29452
30450
|
let tokenToMigrate = null;
|
|
29453
30451
|
for (const key of keys) {
|
|
@@ -29459,8 +30457,8 @@ async function migrateUnencryptedTokens(provider, walletAddress) {
|
|
|
29459
30457
|
}
|
|
29460
30458
|
if (!tokenToMigrate) {
|
|
29461
30459
|
for (const key of keys) {
|
|
29462
|
-
const
|
|
29463
|
-
if (isEncrypted2(localStorage.getItem(key)) &&
|
|
30460
|
+
const stored2 = sessionStorage.getItem(key);
|
|
30461
|
+
if (isEncrypted2(localStorage.getItem(key)) && stored2 && !isEncrypted2(stored2)) {
|
|
29464
30462
|
sessionStorage.removeItem(key);
|
|
29465
30463
|
}
|
|
29466
30464
|
}
|
|
@@ -29516,17 +30514,17 @@ function storeOAuthState2(state) {
|
|
|
29516
30514
|
}
|
|
29517
30515
|
function getAndClearOAuthState4() {
|
|
29518
30516
|
if (typeof window === "undefined") return null;
|
|
29519
|
-
const
|
|
30517
|
+
const stored2 = sessionStorage.getItem(STATE_STORAGE_KEY);
|
|
29520
30518
|
sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
29521
|
-
if (!
|
|
30519
|
+
if (!stored2) return null;
|
|
29522
30520
|
try {
|
|
29523
|
-
const parsed = JSON.parse(
|
|
30521
|
+
const parsed = JSON.parse(stored2);
|
|
29524
30522
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
29525
30523
|
return parsed.state;
|
|
29526
30524
|
}
|
|
29527
30525
|
} catch {
|
|
29528
30526
|
}
|
|
29529
|
-
return
|
|
30527
|
+
return stored2;
|
|
29530
30528
|
}
|
|
29531
30529
|
function isDropboxCallback() {
|
|
29532
30530
|
if (typeof window === "undefined") return false;
|
|
@@ -29710,17 +30708,17 @@ function storeOAuthState3(state) {
|
|
|
29710
30708
|
}
|
|
29711
30709
|
function getAndClearOAuthState5() {
|
|
29712
30710
|
if (typeof window === "undefined") return null;
|
|
29713
|
-
const
|
|
30711
|
+
const stored2 = sessionStorage.getItem(CODE_STORAGE_KEY4);
|
|
29714
30712
|
sessionStorage.removeItem(CODE_STORAGE_KEY4);
|
|
29715
|
-
if (!
|
|
30713
|
+
if (!stored2) return null;
|
|
29716
30714
|
try {
|
|
29717
|
-
const parsed = JSON.parse(
|
|
30715
|
+
const parsed = JSON.parse(stored2);
|
|
29718
30716
|
if (parsed && typeof parsed === "object" && "state" in parsed) {
|
|
29719
30717
|
return parsed.state;
|
|
29720
30718
|
}
|
|
29721
30719
|
} catch {
|
|
29722
30720
|
}
|
|
29723
|
-
return
|
|
30721
|
+
return stored2;
|
|
29724
30722
|
}
|
|
29725
30723
|
function isGoogleDriveCallback() {
|
|
29726
30724
|
if (typeof window === "undefined") return false;
|
|
@@ -31664,18 +32662,18 @@ async function blobToDataUri(blob) {
|
|
|
31664
32662
|
reader.readAsDataURL(blob);
|
|
31665
32663
|
});
|
|
31666
32664
|
}
|
|
31667
|
-
async function storedToLlmapiMessage(
|
|
31668
|
-
let textContent =
|
|
32665
|
+
async function storedToLlmapiMessage(stored2, encryptionKey, resolveMediaByIds) {
|
|
32666
|
+
let textContent = stored2.content;
|
|
31669
32667
|
const fileUrlMap = /* @__PURE__ */ new Map();
|
|
31670
32668
|
const imageParts = [];
|
|
31671
|
-
if (
|
|
31672
|
-
for (const file of
|
|
32669
|
+
if (stored2.role !== "assistant" && stored2.files?.length) {
|
|
32670
|
+
for (const file of stored2.files) {
|
|
31673
32671
|
if (isSendableImageURL(file.url)) {
|
|
31674
32672
|
imageParts.push({
|
|
31675
32673
|
type: "image_url",
|
|
31676
32674
|
image_url: { url: file.url }
|
|
31677
32675
|
});
|
|
31678
|
-
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl,
|
|
32676
|
+
} else if (file.sourceUrl && !isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
31679
32677
|
imageParts.push({
|
|
31680
32678
|
type: "image_url",
|
|
31681
32679
|
image_url: { url: file.sourceUrl }
|
|
@@ -31695,11 +32693,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31695
32693
|
}
|
|
31696
32694
|
}
|
|
31697
32695
|
}
|
|
31698
|
-
} else if (
|
|
32696
|
+
} else if (stored2.role === "assistant" && stored2.files?.length) {
|
|
31699
32697
|
const expiredFileIds = [];
|
|
31700
|
-
for (const file of
|
|
32698
|
+
for (const file of stored2.files) {
|
|
31701
32699
|
if (file.sourceUrl) {
|
|
31702
|
-
if (!isR2UrlExpired(file.sourceUrl,
|
|
32700
|
+
if (!isR2UrlExpired(file.sourceUrl, stored2.createdAt)) {
|
|
31703
32701
|
fileUrlMap.set(file.id, file.sourceUrl);
|
|
31704
32702
|
} else {
|
|
31705
32703
|
expiredFileIds.push(file.id);
|
|
@@ -31712,11 +32710,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31712
32710
|
[${expiredFileIds.length} expired image URL${expiredFileIds.length > 1 ? "s" : ""} omitted \u2014 the user can still see ${expiredFileIds.length > 1 ? "them" : "it"} locally]`;
|
|
31713
32711
|
}
|
|
31714
32712
|
}
|
|
31715
|
-
if (
|
|
32713
|
+
if (stored2.fileIds?.length && resolveMediaByIds) {
|
|
31716
32714
|
try {
|
|
31717
|
-
const mediaItems = await resolveMediaByIds(
|
|
32715
|
+
const mediaItems = await resolveMediaByIds(stored2.fileIds);
|
|
31718
32716
|
for (const media of mediaItems) {
|
|
31719
|
-
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl,
|
|
32717
|
+
if (media.sourceUrl && !isR2UrlExpired(media.sourceUrl, stored2.createdAt)) {
|
|
31720
32718
|
fileUrlMap.set(media.mediaId, media.sourceUrl);
|
|
31721
32719
|
}
|
|
31722
32720
|
}
|
|
@@ -31740,7 +32738,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31740
32738
|
return "";
|
|
31741
32739
|
}
|
|
31742
32740
|
);
|
|
31743
|
-
if (
|
|
32741
|
+
if (stored2.role === "assistant" && fileUrlMap.size > 0) {
|
|
31744
32742
|
const unreferencedImages = [...fileUrlMap.entries()].filter(
|
|
31745
32743
|
([, url]) => !textContent.includes(url)
|
|
31746
32744
|
);
|
|
@@ -31752,11 +32750,11 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31752
32750
|
textContent = textContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
31753
32751
|
const content = [{ type: "text", text: textContent }, ...imageParts];
|
|
31754
32752
|
const messages = [];
|
|
31755
|
-
if (
|
|
32753
|
+
if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
|
|
31756
32754
|
messages.push({
|
|
31757
|
-
role:
|
|
32755
|
+
role: stored2.role,
|
|
31758
32756
|
content: void 0,
|
|
31759
|
-
tool_calls:
|
|
32757
|
+
tool_calls: stored2.toolCallEvents.map((event) => ({
|
|
31760
32758
|
id: event.id,
|
|
31761
32759
|
type: "function",
|
|
31762
32760
|
function: {
|
|
@@ -31765,7 +32763,7 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31765
32763
|
}
|
|
31766
32764
|
}))
|
|
31767
32765
|
});
|
|
31768
|
-
for (const event of
|
|
32766
|
+
for (const event of stored2.toolCallEvents) {
|
|
31769
32767
|
if (event.id && event.output !== void 0 && event.output !== null) {
|
|
31770
32768
|
messages.push({
|
|
31771
32769
|
role: "tool",
|
|
@@ -31776,12 +32774,12 @@ async function storedToLlmapiMessage(stored, encryptionKey, resolveMediaByIds) {
|
|
|
31776
32774
|
}
|
|
31777
32775
|
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
32776
|
messages.push({
|
|
31779
|
-
role:
|
|
32777
|
+
role: stored2.role,
|
|
31780
32778
|
content: [{ type: "text", text: postToolText }]
|
|
31781
32779
|
});
|
|
31782
32780
|
} else {
|
|
31783
32781
|
messages.push({
|
|
31784
|
-
role:
|
|
32782
|
+
role: stored2.role,
|
|
31785
32783
|
content
|
|
31786
32784
|
});
|
|
31787
32785
|
}
|
|
@@ -35600,19 +36598,19 @@ function startObserve(entry, walletAddress) {
|
|
|
35600
36598
|
"updated_at"
|
|
35601
36599
|
]).subscribe({
|
|
35602
36600
|
next: (records) => {
|
|
35603
|
-
const
|
|
35604
|
-
if (!
|
|
36601
|
+
const record2 = records[0];
|
|
36602
|
+
if (!record2) return;
|
|
35605
36603
|
const patch = {
|
|
35606
36604
|
userPreference: {
|
|
35607
|
-
uniqueId:
|
|
35608
|
-
walletAddress:
|
|
35609
|
-
nickname:
|
|
35610
|
-
occupation:
|
|
35611
|
-
description:
|
|
35612
|
-
models:
|
|
35613
|
-
personality:
|
|
35614
|
-
createdAt:
|
|
35615
|
-
updatedAt:
|
|
36605
|
+
uniqueId: record2.id,
|
|
36606
|
+
walletAddress: record2.walletAddress,
|
|
36607
|
+
nickname: record2.nickname,
|
|
36608
|
+
occupation: record2.occupation,
|
|
36609
|
+
description: record2.description,
|
|
36610
|
+
models: record2.models,
|
|
36611
|
+
personality: record2.personality,
|
|
36612
|
+
createdAt: record2.createdAt,
|
|
36613
|
+
updatedAt: record2.updatedAt
|
|
35616
36614
|
}
|
|
35617
36615
|
};
|
|
35618
36616
|
if (isInitialEmission) {
|
|
@@ -36818,7 +37816,10 @@ function useWalletBinding(options = {}) {
|
|
|
36818
37816
|
LoggerProvider,
|
|
36819
37817
|
MAX_HOPS,
|
|
36820
37818
|
MEDIUM_TTL_MS,
|
|
37819
|
+
MEMORY_KINDS,
|
|
37820
|
+
MEMORY_LEVELS,
|
|
36821
37821
|
MemoryEntityModel,
|
|
37822
|
+
MemoryLevelError,
|
|
36822
37823
|
NEVER_TTL_MS,
|
|
36823
37824
|
NODE_BUDGET,
|
|
36824
37825
|
PAST_EVENT_GRACE_MS,
|
|
@@ -36831,6 +37832,7 @@ function useWalletBinding(options = {}) {
|
|
|
36831
37832
|
R2_DEFAULT_TTL_MS,
|
|
36832
37833
|
RECALL_MAX_LIMIT,
|
|
36833
37834
|
RECALL_TOOL_NAME,
|
|
37835
|
+
RemoteMemoryError,
|
|
36834
37836
|
RerankerUnavailableError,
|
|
36835
37837
|
SDK_SCHEMA_VERSION,
|
|
36836
37838
|
SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -36922,6 +37924,8 @@ function useWalletBinding(options = {}) {
|
|
|
36922
37924
|
createPlatformCursorStore,
|
|
36923
37925
|
createProjectOp,
|
|
36924
37926
|
createRecallTool,
|
|
37927
|
+
createRemoteMemoryPersistence,
|
|
37928
|
+
createRemoteMemoryPipeline,
|
|
36925
37929
|
createSavedToolOp,
|
|
36926
37930
|
createServerToolsFilter,
|
|
36927
37931
|
createStockPricePreProcessor,
|