@anuma/sdk 6.34.0 → 6.36.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 +858 -52
- package/dist/expo/index.d.mts +134 -8
- package/dist/expo/index.d.ts +134 -8
- package/dist/expo/index.mjs +848 -52
- package/dist/memory/context.d.mts +21 -1
- package/dist/memory/context.d.ts +21 -1
- package/dist/react/index.cjs +848 -42
- package/dist/react/index.d.mts +134 -8
- package/dist/react/index.d.ts +134 -8
- package/dist/react/index.mjs +838 -42
- package/dist/server/index.cjs +201 -13
- package/dist/server/index.d.mts +61 -8
- package/dist/server/index.d.ts +61 -8
- package/dist/server/index.mjs +198 -13
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -89,9 +89,9 @@ function createSseClient({
|
|
|
89
89
|
if (done) break;
|
|
90
90
|
buffer += value;
|
|
91
91
|
buffer = buffer.replace(/\r\n?/g, "\n");
|
|
92
|
-
const
|
|
93
|
-
buffer =
|
|
94
|
-
for (const chunk of
|
|
92
|
+
const chunks2 = buffer.split("\n\n");
|
|
93
|
+
buffer = chunks2.pop() ?? "";
|
|
94
|
+
for (const chunk of chunks2) {
|
|
95
95
|
const lines = chunk.split("\n");
|
|
96
96
|
const dataLines = [];
|
|
97
97
|
let eventName;
|
|
@@ -4731,14 +4731,14 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
|
|
|
4731
4731
|
});
|
|
4732
4732
|
return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
4733
4733
|
}
|
|
4734
|
-
async function updateMessageChunksOp(ctx, uniqueId,
|
|
4734
|
+
async function updateMessageChunksOp(ctx, uniqueId, chunks2, embeddingModel) {
|
|
4735
4735
|
let message;
|
|
4736
4736
|
try {
|
|
4737
4737
|
message = await ctx.messagesCollection.find(uniqueId);
|
|
4738
4738
|
} catch {
|
|
4739
4739
|
return null;
|
|
4740
4740
|
}
|
|
4741
|
-
const storedChunks =
|
|
4741
|
+
const storedChunks = chunks2.map(({ text: _text, ...rest }) => rest);
|
|
4742
4742
|
await ctx.database.write(async () => {
|
|
4743
4743
|
await message.update((msg) => {
|
|
4744
4744
|
msg._setRaw("chunks", JSON.stringify(storedChunks));
|
|
@@ -4782,12 +4782,12 @@ async function stripLegacyChunkTextOp(ctx) {
|
|
|
4782
4782
|
const messages = await ctx.messagesCollection.query(Q.where("id", Q.oneOf(changedIds))).fetch();
|
|
4783
4783
|
const updates = messages.flatMap((message) => {
|
|
4784
4784
|
const raw = message._raw;
|
|
4785
|
-
const
|
|
4786
|
-
if (!
|
|
4785
|
+
const chunks2 = chunksWithoutText(raw.chunks);
|
|
4786
|
+
if (!chunks2) return [];
|
|
4787
4787
|
const updatedAt = raw.updated_at;
|
|
4788
4788
|
return [
|
|
4789
4789
|
message.prepareUpdate((msg) => {
|
|
4790
|
-
msg._setRaw("chunks", JSON.stringify(
|
|
4790
|
+
msg._setRaw("chunks", JSON.stringify(chunks2));
|
|
4791
4791
|
msg._setRaw("updated_at", updatedAt);
|
|
4792
4792
|
})
|
|
4793
4793
|
];
|
|
@@ -4997,15 +4997,15 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
4997
4997
|
}
|
|
4998
4998
|
continue;
|
|
4999
4999
|
}
|
|
5000
|
-
const
|
|
5001
|
-
if (
|
|
5002
|
-
const vectors =
|
|
5000
|
+
const chunks2 = await readRawJsonField(message, "chunks", ctx.walletAddress);
|
|
5001
|
+
if (chunks2 && chunks2.length > 0) {
|
|
5002
|
+
const vectors = chunks2.map(
|
|
5003
5003
|
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
5004
5004
|
unreadableVectors++;
|
|
5005
5005
|
})
|
|
5006
5006
|
);
|
|
5007
5007
|
chunkCache?.set(message.id, { version, chunks: vectors });
|
|
5008
|
-
for (let ci = 0; ci <
|
|
5008
|
+
for (let ci = 0; ci < chunks2.length; ci++) {
|
|
5009
5009
|
const vec = vectors[ci];
|
|
5010
5010
|
if (vec.length === 0) continue;
|
|
5011
5011
|
const similarity = cosineSimilarity(queryVector, vec);
|
|
@@ -5013,7 +5013,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
5013
5013
|
candidates.push({
|
|
5014
5014
|
message,
|
|
5015
5015
|
similarity,
|
|
5016
|
-
chunkTextSource: { kind: "chunk", chunk:
|
|
5016
|
+
chunkTextSource: { kind: "chunk", chunk: chunks2[ci], siblings: chunks2 }
|
|
5017
5017
|
});
|
|
5018
5018
|
}
|
|
5019
5019
|
}
|
|
@@ -5190,7 +5190,7 @@ function chunkText(text12, options) {
|
|
|
5190
5190
|
];
|
|
5191
5191
|
}
|
|
5192
5192
|
const sentences = splitIntoSentences(text12);
|
|
5193
|
-
const
|
|
5193
|
+
const chunks2 = [];
|
|
5194
5194
|
let currentChunkSentences = [];
|
|
5195
5195
|
let currentChunkStart = 0;
|
|
5196
5196
|
let currentOffset = 0;
|
|
@@ -5204,7 +5204,7 @@ function chunkText(text12, options) {
|
|
|
5204
5204
|
if (sentence.length > chunkSize) {
|
|
5205
5205
|
if (currentChunkSentences.length > 0) {
|
|
5206
5206
|
const chunkText2 = currentChunkSentences.join(" ");
|
|
5207
|
-
|
|
5207
|
+
chunks2.push({
|
|
5208
5208
|
text: chunkText2,
|
|
5209
5209
|
startOffset: currentChunkStart,
|
|
5210
5210
|
endOffset: currentOffset
|
|
@@ -5215,7 +5215,7 @@ function chunkText(text12, options) {
|
|
|
5215
5215
|
const chunkEnd = Math.min(j + chunkSize, sentence.length);
|
|
5216
5216
|
const chunk = sentence.slice(j, chunkEnd);
|
|
5217
5217
|
if (chunk.length >= minChunkSize) {
|
|
5218
|
-
|
|
5218
|
+
chunks2.push({
|
|
5219
5219
|
text: chunk,
|
|
5220
5220
|
startOffset: sentenceStart + j,
|
|
5221
5221
|
endOffset: sentenceStart + chunkEnd
|
|
@@ -5229,7 +5229,7 @@ function chunkText(text12, options) {
|
|
|
5229
5229
|
const currentText = currentChunkSentences.join(" ");
|
|
5230
5230
|
const potentialLength = currentText.length + (currentText ? 1 : 0) + sentence.length;
|
|
5231
5231
|
if (potentialLength > chunkSize && currentChunkSentences.length > 0) {
|
|
5232
|
-
|
|
5232
|
+
chunks2.push({
|
|
5233
5233
|
text: currentText,
|
|
5234
5234
|
startOffset: currentChunkStart,
|
|
5235
5235
|
endOffset: currentOffset
|
|
@@ -5260,14 +5260,14 @@ function chunkText(text12, options) {
|
|
|
5260
5260
|
if (currentChunkSentences.length > 0) {
|
|
5261
5261
|
const chunkText2 = currentChunkSentences.join(" ");
|
|
5262
5262
|
if (chunkText2.length >= minChunkSize) {
|
|
5263
|
-
|
|
5263
|
+
chunks2.push({
|
|
5264
5264
|
text: chunkText2,
|
|
5265
5265
|
startOffset: currentChunkStart,
|
|
5266
5266
|
endOffset: text12.length
|
|
5267
5267
|
});
|
|
5268
5268
|
}
|
|
5269
5269
|
}
|
|
5270
|
-
if (
|
|
5270
|
+
if (chunks2.length === 0) {
|
|
5271
5271
|
const trimmedText = text12.trim();
|
|
5272
5272
|
if (trimmedText.length > 0) {
|
|
5273
5273
|
return [
|
|
@@ -5279,7 +5279,7 @@ function chunkText(text12, options) {
|
|
|
5279
5279
|
];
|
|
5280
5280
|
}
|
|
5281
5281
|
}
|
|
5282
|
-
return
|
|
5282
|
+
return chunks2;
|
|
5283
5283
|
}
|
|
5284
5284
|
function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
|
|
5285
5285
|
return content.length > chunkSize;
|
|
@@ -5497,18 +5497,18 @@ async function embedMany(texts, options, outer) {
|
|
|
5497
5497
|
outer
|
|
5498
5498
|
);
|
|
5499
5499
|
} else {
|
|
5500
|
-
const
|
|
5500
|
+
const chunks2 = [];
|
|
5501
5501
|
for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
|
|
5502
|
-
|
|
5502
|
+
chunks2.push(uncachedTexts.slice(i, i + chunkSize));
|
|
5503
5503
|
}
|
|
5504
|
-
const allEmbeddings = new Array(
|
|
5504
|
+
const allEmbeddings = new Array(chunks2.length);
|
|
5505
5505
|
let nextIndex = 0;
|
|
5506
5506
|
const worker = async () => {
|
|
5507
|
-
while (nextIndex <
|
|
5507
|
+
while (nextIndex < chunks2.length) {
|
|
5508
5508
|
if (outer?.aborted) throw outer.reason;
|
|
5509
5509
|
const idx = nextIndex++;
|
|
5510
5510
|
allEmbeddings[idx] = await generateEmbeddingsBatch(
|
|
5511
|
-
|
|
5511
|
+
chunks2[idx],
|
|
5512
5512
|
headers,
|
|
5513
5513
|
baseUrl,
|
|
5514
5514
|
embeddingModel,
|
|
@@ -5520,7 +5520,7 @@ async function embedMany(texts, options, outer) {
|
|
|
5520
5520
|
}
|
|
5521
5521
|
};
|
|
5522
5522
|
const workers = Array.from(
|
|
5523
|
-
{ length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY,
|
|
5523
|
+
{ length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks2.length) },
|
|
5524
5524
|
() => worker()
|
|
5525
5525
|
);
|
|
5526
5526
|
await Promise.all(workers);
|
|
@@ -11318,6 +11318,15 @@ __decorateClass([
|
|
|
11318
11318
|
__decorateClass([
|
|
11319
11319
|
text6("scope")
|
|
11320
11320
|
], VaultMemory.prototype, "scope", 2);
|
|
11321
|
+
__decorateClass([
|
|
11322
|
+
field5("kind")
|
|
11323
|
+
], VaultMemory.prototype, "kind", 2);
|
|
11324
|
+
__decorateClass([
|
|
11325
|
+
field5("kind_value")
|
|
11326
|
+
], VaultMemory.prototype, "kindValue", 2);
|
|
11327
|
+
__decorateClass([
|
|
11328
|
+
field5("level")
|
|
11329
|
+
], VaultMemory.prototype, "level", 2);
|
|
11321
11330
|
__decorateClass([
|
|
11322
11331
|
field5("folder_id")
|
|
11323
11332
|
], VaultMemory.prototype, "folderId", 2);
|
|
@@ -11543,7 +11552,7 @@ __decorateClass([
|
|
|
11543
11552
|
], VaultFolder.prototype, "context", 2);
|
|
11544
11553
|
|
|
11545
11554
|
// src/lib/db/schema.ts
|
|
11546
|
-
var SDK_SCHEMA_VERSION =
|
|
11555
|
+
var SDK_SCHEMA_VERSION = 48;
|
|
11547
11556
|
var sdkSchema = appSchema2({
|
|
11548
11557
|
version: SDK_SCHEMA_VERSION,
|
|
11549
11558
|
tables: [
|
|
@@ -11638,6 +11647,9 @@ var sdkSchema = appSchema2({
|
|
|
11638
11647
|
columns: [
|
|
11639
11648
|
{ name: "content", type: "string" },
|
|
11640
11649
|
{ name: "scope", type: "string", isIndexed: true },
|
|
11650
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
11651
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
11652
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true },
|
|
11641
11653
|
{ name: "folder_id", type: "string", isOptional: true, isIndexed: true },
|
|
11642
11654
|
{ name: "created_at", type: "number", isIndexed: true },
|
|
11643
11655
|
{ name: "updated_at", type: "number", isIndexed: true },
|
|
@@ -12314,6 +12326,22 @@ var sdkMigrations = schemaMigrations2({
|
|
|
12314
12326
|
]
|
|
12315
12327
|
})
|
|
12316
12328
|
]
|
|
12329
|
+
},
|
|
12330
|
+
{
|
|
12331
|
+
toVersion: 48,
|
|
12332
|
+
steps: [
|
|
12333
|
+
addColumns2({
|
|
12334
|
+
table: "memory_vault",
|
|
12335
|
+
columns: [
|
|
12336
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
12337
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
12338
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true }
|
|
12339
|
+
]
|
|
12340
|
+
}),
|
|
12341
|
+
unsafeExecuteSql(
|
|
12342
|
+
"UPDATE memory_vault SET level = CASE WHEN scope IN ('shared', 'public') THEN 'matching' ELSE 'private' END WHERE level IS NULL;"
|
|
12343
|
+
)
|
|
12344
|
+
]
|
|
12317
12345
|
}
|
|
12318
12346
|
]
|
|
12319
12347
|
});
|
|
@@ -12835,8 +12863,8 @@ var WatermelonChatStorageAdapter = class {
|
|
|
12835
12863
|
updateMessageEmbedding(uniqueId, vector, embeddingModel) {
|
|
12836
12864
|
return updateMessageEmbeddingOp(this.ctx, uniqueId, vector, embeddingModel);
|
|
12837
12865
|
}
|
|
12838
|
-
updateMessageChunks(uniqueId,
|
|
12839
|
-
return updateMessageChunksOp(this.ctx, uniqueId,
|
|
12866
|
+
updateMessageChunks(uniqueId, chunks2, embeddingModel) {
|
|
12867
|
+
return updateMessageChunksOp(this.ctx, uniqueId, chunks2, embeddingModel);
|
|
12840
12868
|
}
|
|
12841
12869
|
updateMessageError(uniqueId, error) {
|
|
12842
12870
|
return updateMessageErrorOp(this.ctx, uniqueId, error);
|
|
@@ -13450,13 +13478,54 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
13450
13478
|
}
|
|
13451
13479
|
}
|
|
13452
13480
|
const decryptedContent = await decryptField(memory.content, address);
|
|
13481
|
+
const decryptedKindValue = typeof memory.kindValue === "string" ? await decryptField(memory.kindValue, address) : memory.kindValue;
|
|
13453
13482
|
return {
|
|
13454
13483
|
...memory,
|
|
13455
|
-
content: decryptedContent
|
|
13484
|
+
content: decryptedContent,
|
|
13485
|
+
...decryptedKindValue !== void 0 && { kindValue: decryptedKindValue }
|
|
13456
13486
|
};
|
|
13457
13487
|
}
|
|
13458
13488
|
|
|
13459
13489
|
// src/lib/db/memoryVault/types.ts
|
|
13490
|
+
var MEMORY_KINDS = [
|
|
13491
|
+
"display_name",
|
|
13492
|
+
"birth_date",
|
|
13493
|
+
"bio",
|
|
13494
|
+
"occupation",
|
|
13495
|
+
"interest",
|
|
13496
|
+
"gender",
|
|
13497
|
+
"height_cm",
|
|
13498
|
+
"looking_for",
|
|
13499
|
+
"politics",
|
|
13500
|
+
"religion",
|
|
13501
|
+
"ethnicity",
|
|
13502
|
+
"smoking",
|
|
13503
|
+
"drinking",
|
|
13504
|
+
"exercise",
|
|
13505
|
+
"sexuality",
|
|
13506
|
+
"prompt"
|
|
13507
|
+
];
|
|
13508
|
+
var MEMORY_LEVELS = ["private", "matching", "profile"];
|
|
13509
|
+
var MemoryLevelError = class extends Error {
|
|
13510
|
+
constructor(message) {
|
|
13511
|
+
super(message);
|
|
13512
|
+
this.name = "MemoryLevelError";
|
|
13513
|
+
}
|
|
13514
|
+
};
|
|
13515
|
+
var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
|
|
13516
|
+
function levelFromScope(scope) {
|
|
13517
|
+
return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
|
|
13518
|
+
}
|
|
13519
|
+
function scopeForLevel(level) {
|
|
13520
|
+
return level === "private" ? "private" : "shared";
|
|
13521
|
+
}
|
|
13522
|
+
function resolveMemoryLevel(level, scope) {
|
|
13523
|
+
return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
|
|
13524
|
+
}
|
|
13525
|
+
function levelForScopeChange(current, nextScope) {
|
|
13526
|
+
const implied = levelFromScope(nextScope);
|
|
13527
|
+
return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
|
|
13528
|
+
}
|
|
13460
13529
|
function parseMedia(value) {
|
|
13461
13530
|
if (typeof value !== "string" || value === "") return null;
|
|
13462
13531
|
try {
|
|
@@ -13486,6 +13555,56 @@ function visibilityConditions(requested) {
|
|
|
13486
13555
|
if (excluded.length === 0) return [];
|
|
13487
13556
|
return [Q8.or(Q8.where("visibility", null), Q8.where("visibility", Q8.notIn(excluded)))];
|
|
13488
13557
|
}
|
|
13558
|
+
function isKinded(record2) {
|
|
13559
|
+
return record2.kind !== null && record2.kind !== void 0;
|
|
13560
|
+
}
|
|
13561
|
+
function assertValidKindLevel(kind, level) {
|
|
13562
|
+
const hasKind = kind !== null && kind !== void 0;
|
|
13563
|
+
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
13564
|
+
throw new MemoryLevelError(`Unknown memory kind: ${kind}`);
|
|
13565
|
+
}
|
|
13566
|
+
if (level !== void 0 && !MEMORY_LEVELS.includes(level)) {
|
|
13567
|
+
throw new MemoryLevelError(`Unknown memory level: ${level}`);
|
|
13568
|
+
}
|
|
13569
|
+
if (level === "profile" && !hasKind) {
|
|
13570
|
+
throw new MemoryLevelError("Only a memory with a kind can be at level 'profile'");
|
|
13571
|
+
}
|
|
13572
|
+
}
|
|
13573
|
+
function resolveCreateLevel(opts) {
|
|
13574
|
+
if (opts.level !== void 0) return { level: opts.level, scope: scopeForLevel(opts.level) };
|
|
13575
|
+
if (opts.scope !== void 0) return { level: levelFromScope(opts.scope), scope: opts.scope };
|
|
13576
|
+
return { level: "private", scope: "private" };
|
|
13577
|
+
}
|
|
13578
|
+
async function encryptKindValue(ctx, value) {
|
|
13579
|
+
if (typeof value !== "string" || !ctx.walletAddress || !ctx.signMessage) return value;
|
|
13580
|
+
return encryptVaultMemoryContent(
|
|
13581
|
+
value,
|
|
13582
|
+
ctx.walletAddress,
|
|
13583
|
+
ctx.signMessage,
|
|
13584
|
+
ctx.embeddedWalletSigner
|
|
13585
|
+
);
|
|
13586
|
+
}
|
|
13587
|
+
function levelConditions(requested) {
|
|
13588
|
+
if (!requested?.length) return [];
|
|
13589
|
+
const published = ["shared", "public"];
|
|
13590
|
+
const wantsMatching = requested.includes("matching");
|
|
13591
|
+
const wantsPrivate = requested.includes("private");
|
|
13592
|
+
const unresolved = Q8.or(Q8.where("level", null), Q8.where("level", Q8.notIn([...MEMORY_LEVELS])));
|
|
13593
|
+
const byLevel = Q8.where("level", Q8.oneOf([...requested]));
|
|
13594
|
+
if (wantsMatching && wantsPrivate) return [Q8.or(byLevel, unresolved)];
|
|
13595
|
+
if (wantsMatching) {
|
|
13596
|
+
return [Q8.or(byLevel, Q8.and(unresolved, Q8.where("scope", Q8.oneOf(published))))];
|
|
13597
|
+
}
|
|
13598
|
+
if (wantsPrivate) {
|
|
13599
|
+
return [
|
|
13600
|
+
Q8.or(
|
|
13601
|
+
byLevel,
|
|
13602
|
+
Q8.and(unresolved, Q8.or(Q8.where("scope", null), Q8.where("scope", Q8.notIn(published))))
|
|
13603
|
+
)
|
|
13604
|
+
];
|
|
13605
|
+
}
|
|
13606
|
+
return [byLevel];
|
|
13607
|
+
}
|
|
13489
13608
|
function isOwnedByCtxUser(ctx, record2) {
|
|
13490
13609
|
return ctx.userId === void 0 || record2.userId === ctx.userId;
|
|
13491
13610
|
}
|
|
@@ -13529,6 +13648,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
13529
13648
|
uniqueId: memory.id,
|
|
13530
13649
|
content: memory.content,
|
|
13531
13650
|
scope: memory.scope,
|
|
13651
|
+
kind: memory.kind ?? null,
|
|
13652
|
+
kindValue: memory.kindValue ?? null,
|
|
13653
|
+
level: resolveMemoryLevel(memory.level, memory.scope),
|
|
13532
13654
|
folderId: memory.folderId ?? null,
|
|
13533
13655
|
userId: memory.userId ?? null,
|
|
13534
13656
|
embedding: memory.embedding ?? null,
|
|
@@ -13567,9 +13689,13 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
13567
13689
|
}
|
|
13568
13690
|
return raw;
|
|
13569
13691
|
}
|
|
13570
|
-
function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
|
|
13692
|
+
function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue) {
|
|
13693
|
+
const { level, scope } = resolveCreateLevel(opts);
|
|
13571
13694
|
record2._setRaw("content", encryptedContent);
|
|
13572
|
-
record2._setRaw("scope",
|
|
13695
|
+
record2._setRaw("scope", scope);
|
|
13696
|
+
record2._setRaw("level", level);
|
|
13697
|
+
record2._setRaw("kind", opts.kind ?? null);
|
|
13698
|
+
record2._setRaw("kind_value", encryptedKindValue ?? null);
|
|
13573
13699
|
record2._setRaw("folder_id", opts.folderId ?? null);
|
|
13574
13700
|
record2._setRaw("user_id", ctx.userId ?? null);
|
|
13575
13701
|
record2._setRaw("is_deleted", false);
|
|
@@ -13603,6 +13729,8 @@ function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
|
|
|
13603
13729
|
}
|
|
13604
13730
|
}
|
|
13605
13731
|
async function createVaultMemoryOp(ctx, opts) {
|
|
13732
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
13733
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
13606
13734
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
13607
13735
|
opts.content,
|
|
13608
13736
|
ctx.walletAddress,
|
|
@@ -13613,13 +13741,15 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
13613
13741
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
13614
13742
|
throw new Error("Memory source is no longer eligible");
|
|
13615
13743
|
return ctx.vaultMemoryCollection.create(
|
|
13616
|
-
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
13744
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13617
13745
|
);
|
|
13618
13746
|
});
|
|
13619
13747
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
13620
13748
|
}
|
|
13621
13749
|
async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
13622
13750
|
if (!targetId) return { created: null, retired: false };
|
|
13751
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
13752
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
13623
13753
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
13624
13754
|
opts.content,
|
|
13625
13755
|
ctx.walletAddress,
|
|
@@ -13636,9 +13766,10 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
13636
13766
|
} catch {
|
|
13637
13767
|
return;
|
|
13638
13768
|
}
|
|
13639
|
-
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target))
|
|
13769
|
+
if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
|
|
13770
|
+
return;
|
|
13640
13771
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
13641
|
-
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
13772
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13642
13773
|
);
|
|
13643
13774
|
await target.update((r) => {
|
|
13644
13775
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -13702,6 +13833,10 @@ async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
|
|
|
13702
13833
|
}
|
|
13703
13834
|
async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
13704
13835
|
if (optionsArray.length === 0) return [];
|
|
13836
|
+
for (const opts of optionsArray) assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
13837
|
+
const encryptedKindValues = await Promise.all(
|
|
13838
|
+
optionsArray.map((opts) => encryptKindValue(ctx, opts.kindValue))
|
|
13839
|
+
);
|
|
13705
13840
|
const encryptedContents = await Promise.all(
|
|
13706
13841
|
optionsArray.map(async (opts) => {
|
|
13707
13842
|
if (ctx.walletAddress && ctx.signMessage) {
|
|
@@ -13720,7 +13855,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13720
13855
|
throw new Error("Memory source is no longer eligible");
|
|
13721
13856
|
const prepared = optionsArray.map(
|
|
13722
13857
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
13723
|
-
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
|
|
13858
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
13724
13859
|
)
|
|
13725
13860
|
);
|
|
13726
13861
|
await ctx.database.batch(...prepared);
|
|
@@ -13763,6 +13898,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
13763
13898
|
uniqueId: raw.id,
|
|
13764
13899
|
content: raw.content ?? "",
|
|
13765
13900
|
scope: raw.scope ?? "",
|
|
13901
|
+
kind: raw.kind ?? null,
|
|
13902
|
+
kindValue: raw.kind_value ?? null,
|
|
13903
|
+
level: resolveMemoryLevel(raw.level, raw.scope),
|
|
13766
13904
|
folderId: raw.folder_id ?? null,
|
|
13767
13905
|
userId: raw.user_id ?? null,
|
|
13768
13906
|
embedding: raw.embedding ?? null,
|
|
@@ -13806,6 +13944,8 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
13806
13944
|
...baseVaultConditions(ctx, options),
|
|
13807
13945
|
...options?.scopes?.length ? [Q8.where("scope", Q8.oneOf(options.scopes))] : [],
|
|
13808
13946
|
...visibilityConditions(options?.visibility),
|
|
13947
|
+
...levelConditions(options?.levels),
|
|
13948
|
+
...options?.kinds?.length ? [Q8.where("kind", Q8.oneOf(options.kinds))] : [],
|
|
13809
13949
|
...options?.folderId !== void 0 ? [Q8.where("folder_id", options.folderId)] : [],
|
|
13810
13950
|
...options?.factTypes?.length ? [Q8.where("fact_type", Q8.oneOf(options.factTypes))] : [],
|
|
13811
13951
|
Q8.sortBy(options?.since ? "updated_at" : "created_at", Q8.desc),
|
|
@@ -13972,6 +14112,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13972
14112
|
try {
|
|
13973
14113
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
13974
14114
|
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
14115
|
+
if (opts.freeFormOnly && isKinded(probe)) return null;
|
|
14116
|
+
const levelAfter = (current) => {
|
|
14117
|
+
if (opts.level !== void 0) return opts.level;
|
|
14118
|
+
if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
|
|
14119
|
+
return levelForScopeChange(current, opts.scope);
|
|
14120
|
+
};
|
|
14121
|
+
assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
|
|
14122
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
13975
14123
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
13976
14124
|
opts.content,
|
|
13977
14125
|
ctx.walletAddress,
|
|
@@ -13984,10 +14132,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13984
14132
|
await ctx.database.write(async () => {
|
|
13985
14133
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
13986
14134
|
throw new Error("Memory source is no longer eligible");
|
|
13987
|
-
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
14135
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
13988
14136
|
stale = true;
|
|
13989
14137
|
return;
|
|
13990
14138
|
}
|
|
14139
|
+
const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
|
|
14140
|
+
const nextLevel = levelAfter(record2);
|
|
14141
|
+
assertValidKindLevel(nextKind, nextLevel);
|
|
13991
14142
|
let observedSources = [];
|
|
13992
14143
|
let replayedObservation = false;
|
|
13993
14144
|
if (opts.observationSourceIds?.length) {
|
|
@@ -14001,8 +14152,18 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
14001
14152
|
}
|
|
14002
14153
|
await record2.update((r) => {
|
|
14003
14154
|
r._setRaw("content", encryptedContent);
|
|
14004
|
-
if (opts.
|
|
14155
|
+
if (opts.level !== void 0) {
|
|
14156
|
+
r._setRaw("level", nextLevel);
|
|
14157
|
+
r._setRaw("scope", scopeForLevel(nextLevel));
|
|
14158
|
+
} else if (opts.scope !== void 0) {
|
|
14005
14159
|
r._setRaw("scope", opts.scope);
|
|
14160
|
+
r._setRaw("level", nextLevel);
|
|
14161
|
+
}
|
|
14162
|
+
if (opts.kind !== void 0) {
|
|
14163
|
+
r._setRaw("kind", opts.kind);
|
|
14164
|
+
}
|
|
14165
|
+
if (encryptedKindValue !== void 0) {
|
|
14166
|
+
r._setRaw("kind_value", encryptedKindValue);
|
|
14006
14167
|
}
|
|
14007
14168
|
if (opts.folderId !== void 0) {
|
|
14008
14169
|
r._setRaw("folder_id", opts.folderId);
|
|
@@ -14061,7 +14222,8 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
14061
14222
|
ctx.signMessage,
|
|
14062
14223
|
ctx.embeddedWalletSigner
|
|
14063
14224
|
);
|
|
14064
|
-
} catch {
|
|
14225
|
+
} catch (err) {
|
|
14226
|
+
if (err instanceof MemoryLevelError) throw err;
|
|
14065
14227
|
return null;
|
|
14066
14228
|
}
|
|
14067
14229
|
}
|
|
@@ -14197,6 +14359,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
14197
14359
|
try {
|
|
14198
14360
|
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
14199
14361
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14362
|
+
if (isKinded(record2)) return false;
|
|
14200
14363
|
let successor;
|
|
14201
14364
|
try {
|
|
14202
14365
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -14497,7 +14660,10 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
14497
14660
|
}
|
|
14498
14661
|
async function getDecayCandidatesRawOp(ctx) {
|
|
14499
14662
|
assertVaultScopeForSweep(ctx);
|
|
14500
|
-
const results = await ctx.vaultMemoryCollection.query(
|
|
14663
|
+
const results = await ctx.vaultMemoryCollection.query(
|
|
14664
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
14665
|
+
Q8.where("kind", null)
|
|
14666
|
+
).unsafeFetchRaw();
|
|
14501
14667
|
return results.map((raw) => ({
|
|
14502
14668
|
uniqueId: raw.id,
|
|
14503
14669
|
factType: raw.fact_type ?? null,
|
|
@@ -14757,6 +14923,7 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
14757
14923
|
record2._raw.id = row.memoryId;
|
|
14758
14924
|
record2._setRaw("content", content);
|
|
14759
14925
|
record2._setRaw("scope", "shared");
|
|
14926
|
+
record2._setRaw("level", "matching");
|
|
14760
14927
|
record2._setRaw("folder_id", null);
|
|
14761
14928
|
record2._setRaw("user_id", ctx.userId ?? null);
|
|
14762
14929
|
record2._setRaw("is_deleted", false);
|
|
@@ -15622,6 +15789,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
15622
15789
|
for (const memory of memories) {
|
|
15623
15790
|
updates.push(
|
|
15624
15791
|
memory.prepareUpdate((r) => {
|
|
15792
|
+
r._setRaw("level", levelForScopeChange(r, opts.scope));
|
|
15625
15793
|
r._setRaw("scope", opts.scope);
|
|
15626
15794
|
})
|
|
15627
15795
|
);
|
|
@@ -15643,6 +15811,7 @@ async function deleteVaultFolderOp(ctx, id) {
|
|
|
15643
15811
|
const preparedMemories = memories.map(
|
|
15644
15812
|
(memory) => memory.prepareUpdate((r) => {
|
|
15645
15813
|
r._setRaw("folder_id", null);
|
|
15814
|
+
r._setRaw("level", levelForScopeChange(r, "private"));
|
|
15646
15815
|
r._setRaw("scope", "private");
|
|
15647
15816
|
})
|
|
15648
15817
|
);
|
|
@@ -15679,6 +15848,7 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
15679
15848
|
const prepared = memories.map(
|
|
15680
15849
|
(memory) => memory.prepareUpdate((r) => {
|
|
15681
15850
|
r._setRaw("folder_id", folderId);
|
|
15851
|
+
r._setRaw("level", levelForScopeChange(r, targetScope));
|
|
15682
15852
|
r._setRaw("scope", targetScope);
|
|
15683
15853
|
})
|
|
15684
15854
|
);
|
|
@@ -17986,6 +18156,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
17986
18156
|
includeArchived: true,
|
|
17987
18157
|
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
17988
18158
|
});
|
|
18159
|
+
prepared = withoutKindedRows(prepared);
|
|
17989
18160
|
if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
|
|
17990
18161
|
throw new Error(
|
|
17991
18162
|
"retain: embeddings unavailable \u2014 refusing to auto-merge against an inert cosine lane, which would create a duplicate instead of merging into the existing memory. Retry when embeddings recover, or pass enableAutoMerge: false to force a create."
|
|
@@ -18027,6 +18198,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
18027
18198
|
const resurrect = resurrectFields(existing);
|
|
18028
18199
|
const updated = await ctx.persistence.update(targetId, {
|
|
18029
18200
|
content: existing.content,
|
|
18201
|
+
freeFormOnly: true,
|
|
18030
18202
|
proofCountIncrement: 1,
|
|
18031
18203
|
observationSourceIds: options.sourceChunkIds,
|
|
18032
18204
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -18155,6 +18327,17 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
18155
18327
|
...consolidationDecidedCreate && { consolidation: "create" }
|
|
18156
18328
|
};
|
|
18157
18329
|
}
|
|
18330
|
+
function withoutKindedRows(prepared) {
|
|
18331
|
+
const kinded = new Set(
|
|
18332
|
+
prepared.memories.filter((m) => m.kind !== null && m.kind !== void 0).map((m) => m.uniqueId)
|
|
18333
|
+
);
|
|
18334
|
+
if (kinded.size === 0) return prepared;
|
|
18335
|
+
return {
|
|
18336
|
+
...prepared,
|
|
18337
|
+
memories: prepared.memories.filter((m) => !kinded.has(m.uniqueId)),
|
|
18338
|
+
embeddedItems: prepared.embeddedItems.filter((item) => !kinded.has(item.id))
|
|
18339
|
+
};
|
|
18340
|
+
}
|
|
18158
18341
|
function unionStrings(a, b) {
|
|
18159
18342
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
18160
18343
|
}
|
|
@@ -18254,6 +18437,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18254
18437
|
const resurrect = resurrectFields(existing);
|
|
18255
18438
|
const updated = await ctx.persistence.update(decision.targetId, {
|
|
18256
18439
|
content: existing.content,
|
|
18440
|
+
freeFormOnly: true,
|
|
18257
18441
|
proofCountIncrement: 1,
|
|
18258
18442
|
observationSourceIds: options.sourceChunkIds,
|
|
18259
18443
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -18299,6 +18483,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18299
18483
|
const resurrect = resurrectFields(existing);
|
|
18300
18484
|
const updated = await ctx.persistence.update(decision.targetId, {
|
|
18301
18485
|
content: decision.content,
|
|
18486
|
+
freeFormOnly: true,
|
|
18302
18487
|
proofCountIncrement: 1,
|
|
18303
18488
|
observationSourceIds: options.sourceChunkIds,
|
|
18304
18489
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -18342,7 +18527,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
18342
18527
|
}
|
|
18343
18528
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
18344
18529
|
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
18345
|
-
if (stillExists) {
|
|
18530
|
+
if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
|
|
18346
18531
|
throw new Error(`retain: merge into memory ${targetId} failed to persist`);
|
|
18347
18532
|
}
|
|
18348
18533
|
}
|
|
@@ -20984,6 +21169,65 @@ function createLocalMemoryStore(options) {
|
|
|
20984
21169
|
};
|
|
20985
21170
|
}
|
|
20986
21171
|
|
|
21172
|
+
// src/lib/memory/store/memoryKeys.ts
|
|
21173
|
+
var KEY_ID_DOMAIN = "anuma-private-memory-key-id-v1";
|
|
21174
|
+
var MemoryKeyError = class extends Error {
|
|
21175
|
+
constructor(message) {
|
|
21176
|
+
super(message);
|
|
21177
|
+
this.name = "MemoryKeyError";
|
|
21178
|
+
}
|
|
21179
|
+
};
|
|
21180
|
+
async function importAesKey(hex) {
|
|
21181
|
+
return crypto.subtle.importKey(
|
|
21182
|
+
"raw",
|
|
21183
|
+
hexToBytes(hex).buffer,
|
|
21184
|
+
{ name: "AES-GCM" },
|
|
21185
|
+
false,
|
|
21186
|
+
["encrypt", "decrypt"]
|
|
21187
|
+
);
|
|
21188
|
+
}
|
|
21189
|
+
async function deriveMemoryKeyRing(signatureHex) {
|
|
21190
|
+
const v3Hex = await deriveKeyFromSignatureV3(signatureHex);
|
|
21191
|
+
const digest = await crypto.subtle.digest(
|
|
21192
|
+
"SHA-256",
|
|
21193
|
+
new TextEncoder().encode(`${KEY_ID_DOMAIN}:${v3Hex}`)
|
|
21194
|
+
);
|
|
21195
|
+
const keyId = "v3:" + Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
21196
|
+
return {
|
|
21197
|
+
keyId,
|
|
21198
|
+
v3: await importAesKey(v3Hex),
|
|
21199
|
+
v2: await importAesKey(await deriveKeyFromSignature(signatureHex))
|
|
21200
|
+
};
|
|
21201
|
+
}
|
|
21202
|
+
async function decryptWith(value, rings) {
|
|
21203
|
+
const version = value.startsWith("enc:v3:") ? "v3" : "v2";
|
|
21204
|
+
for (const ring of rings) {
|
|
21205
|
+
try {
|
|
21206
|
+
return await decryptDataWithKey(value.slice(`enc:${version}:`.length), ring[version]);
|
|
21207
|
+
} catch {
|
|
21208
|
+
continue;
|
|
21209
|
+
}
|
|
21210
|
+
}
|
|
21211
|
+
throw new MemoryKeyError(`No supplied key decrypts this enc:${version} field`);
|
|
21212
|
+
}
|
|
21213
|
+
function memoryCipher(canonical) {
|
|
21214
|
+
return {
|
|
21215
|
+
encrypt: async (plaintext) => `enc:v3:${await encryptDataWithKey(plaintext, canonical.v3)}`,
|
|
21216
|
+
decrypt: async (ciphertext) => {
|
|
21217
|
+
if (!ciphertext.startsWith("enc:v3:") || !isEncrypted(ciphertext))
|
|
21218
|
+
throw new MemoryKeyError("Remote memory content must be enc:v3 ciphertext");
|
|
21219
|
+
return decryptWith(ciphertext, [canonical]);
|
|
21220
|
+
}
|
|
21221
|
+
};
|
|
21222
|
+
}
|
|
21223
|
+
async function reencryptMemoryField(value, canonical, fallbacks = []) {
|
|
21224
|
+
const { encrypt } = memoryCipher(canonical);
|
|
21225
|
+
if (!value.startsWith("enc:")) return encrypt(value);
|
|
21226
|
+
if (!isEncrypted(value))
|
|
21227
|
+
throw new MemoryKeyError("Field has an encryption prefix but an invalid payload");
|
|
21228
|
+
return encrypt(await decryptWith(value, [canonical, ...fallbacks]));
|
|
21229
|
+
}
|
|
21230
|
+
|
|
20987
21231
|
// src/lib/memory/store/remotePersistence.ts
|
|
20988
21232
|
var RemoteMemoryError = class extends Error {
|
|
20989
21233
|
constructor(message, status, code) {
|
|
@@ -21036,6 +21280,30 @@ var candidateListLimits = [
|
|
|
21036
21280
|
["memory_ids", 1e3],
|
|
21037
21281
|
["force_ids", 100]
|
|
21038
21282
|
];
|
|
21283
|
+
var queryListLimits = [
|
|
21284
|
+
["scopes", 20],
|
|
21285
|
+
["fact_types", 20],
|
|
21286
|
+
["visibility", 20],
|
|
21287
|
+
["memory_ids", 1e3],
|
|
21288
|
+
["topics", 100]
|
|
21289
|
+
];
|
|
21290
|
+
var queryFields = [
|
|
21291
|
+
"include_deleted",
|
|
21292
|
+
"include_archived",
|
|
21293
|
+
"include_quarantined",
|
|
21294
|
+
"include_superseded",
|
|
21295
|
+
"archived_only",
|
|
21296
|
+
"scopes",
|
|
21297
|
+
"fact_types",
|
|
21298
|
+
"visibility",
|
|
21299
|
+
"memory_ids",
|
|
21300
|
+
"topics",
|
|
21301
|
+
"updated_after",
|
|
21302
|
+
"order",
|
|
21303
|
+
"cursor",
|
|
21304
|
+
"limit",
|
|
21305
|
+
"include_embeddings"
|
|
21306
|
+
];
|
|
21039
21307
|
function record(value) {
|
|
21040
21308
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21041
21309
|
}
|
|
@@ -21370,6 +21638,35 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
21370
21638
|
throw new Error("Invalid nearby batch response");
|
|
21371
21639
|
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
21372
21640
|
},
|
|
21641
|
+
query: async (queryOptions = {}) => {
|
|
21642
|
+
const { signal, ...query } = queryOptions;
|
|
21643
|
+
if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200))
|
|
21644
|
+
throw new Error("Page limit must be 1\u2013200");
|
|
21645
|
+
for (const [key, max] of queryListLimits) {
|
|
21646
|
+
const values = query[key];
|
|
21647
|
+
if (values && values.length > max)
|
|
21648
|
+
throw new Error(`Query ${key} accepts at most ${max} entries (got ${values.length})`);
|
|
21649
|
+
}
|
|
21650
|
+
const page = await request(
|
|
21651
|
+
"/memories/query",
|
|
21652
|
+
{
|
|
21653
|
+
method: "POST",
|
|
21654
|
+
body: JSON.stringify(
|
|
21655
|
+
Object.fromEntries(
|
|
21656
|
+
queryFields.filter((key) => query[key] !== void 0).map((key) => [key, query[key]])
|
|
21657
|
+
)
|
|
21658
|
+
)
|
|
21659
|
+
},
|
|
21660
|
+
signal
|
|
21661
|
+
);
|
|
21662
|
+
if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string" || page.changes_cursor !== void 0 && typeof page.changes_cursor !== "string")
|
|
21663
|
+
throw new Error("Invalid nearby private-memory page");
|
|
21664
|
+
return {
|
|
21665
|
+
...await decodeAll(page.items),
|
|
21666
|
+
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor },
|
|
21667
|
+
...page.changes_cursor !== void 0 && { changes_cursor: page.changes_cursor }
|
|
21668
|
+
};
|
|
21669
|
+
},
|
|
21373
21670
|
candidateSet,
|
|
21374
21671
|
candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
|
|
21375
21672
|
};
|
|
@@ -21394,6 +21691,9 @@ function sourceIds(value) {
|
|
|
21394
21691
|
return [];
|
|
21395
21692
|
}
|
|
21396
21693
|
}
|
|
21694
|
+
function isMemoryLevel(value) {
|
|
21695
|
+
return MEMORY_LEVELS.includes(value);
|
|
21696
|
+
}
|
|
21397
21697
|
function stored(row) {
|
|
21398
21698
|
return {
|
|
21399
21699
|
uniqueId: row.memory_id,
|
|
@@ -21401,6 +21701,9 @@ function stored(row) {
|
|
|
21401
21701
|
scope: row.scope,
|
|
21402
21702
|
folderId: row.folder_id ?? null,
|
|
21403
21703
|
userId: null,
|
|
21704
|
+
kind: row.kind ?? null,
|
|
21705
|
+
kindValue: row.kind_value ?? null,
|
|
21706
|
+
...isMemoryLevel(row.level) && { level: row.level },
|
|
21404
21707
|
embedding: row.embedding ? JSON.stringify(row.embedding) : null,
|
|
21405
21708
|
embeddingModel: row.embedding_model ?? null,
|
|
21406
21709
|
sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
|
|
@@ -21622,7 +21925,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21622
21925
|
create: (input) => write(createRow(input), 0),
|
|
21623
21926
|
update: async (id, patch) => {
|
|
21624
21927
|
const existing = await get(id);
|
|
21625
|
-
if (!existing
|
|
21928
|
+
if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
|
|
21929
|
+
return null;
|
|
21626
21930
|
const snapshot = snapshots.get(id);
|
|
21627
21931
|
const memory = {
|
|
21628
21932
|
...snapshot.memory,
|
|
@@ -21751,6 +22055,489 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21751
22055
|
};
|
|
21752
22056
|
}
|
|
21753
22057
|
|
|
22058
|
+
// src/lib/memory/store/remoteStore.ts
|
|
22059
|
+
import { v7 as uuidv76 } from "uuid";
|
|
22060
|
+
function relevant(change, options) {
|
|
22061
|
+
return options.includeDeleted ? change === "membership" : change !== "embedding" || !!options.embeddings;
|
|
22062
|
+
}
|
|
22063
|
+
function safely(onChange) {
|
|
22064
|
+
try {
|
|
22065
|
+
onChange();
|
|
22066
|
+
} catch (error) {
|
|
22067
|
+
getLogger().warn("[memory/remote-store] Subscriber threw:", error);
|
|
22068
|
+
}
|
|
22069
|
+
}
|
|
22070
|
+
var MAX_BATCH = 50;
|
|
22071
|
+
var MAX_QUERY_IDS = 1e3;
|
|
22072
|
+
var MAX_QUERY_TOPICS = 100;
|
|
22073
|
+
var MAX_QUERY_FILTER = 20;
|
|
22074
|
+
var RemoteMemoryPartialCreateError = class extends Error {
|
|
22075
|
+
constructor(created, cause) {
|
|
22076
|
+
super(`createMany stored ${created.length} memories before a batch failed`);
|
|
22077
|
+
this.created = created;
|
|
22078
|
+
this.cause = cause;
|
|
22079
|
+
this.name = "RemoteMemoryPartialCreateError";
|
|
22080
|
+
}
|
|
22081
|
+
};
|
|
22082
|
+
function warnFailed(failed) {
|
|
22083
|
+
if (failed.length)
|
|
22084
|
+
getLogger().warn(
|
|
22085
|
+
`[memory/remote-store] Skipping ${failed.length} undecryptable row(s)`,
|
|
22086
|
+
failed.map((failure) => failure.memory_id)
|
|
22087
|
+
);
|
|
22088
|
+
}
|
|
22089
|
+
function bounded(filters, key) {
|
|
22090
|
+
const values = filters[key];
|
|
22091
|
+
if (!values || values.length <= MAX_QUERY_FILTER) return [filters];
|
|
22092
|
+
return chunks(values, MAX_QUERY_FILTER).map((chunk) => ({ ...filters, [key]: chunk }));
|
|
22093
|
+
}
|
|
22094
|
+
function chunks(values, size) {
|
|
22095
|
+
const out = [];
|
|
22096
|
+
for (let i = 0; i < values.length; i += size) out.push(values.slice(i, i + size));
|
|
22097
|
+
return out;
|
|
22098
|
+
}
|
|
22099
|
+
function stateFilters(options) {
|
|
22100
|
+
return {
|
|
22101
|
+
include_deleted: options.includeDeleted,
|
|
22102
|
+
include_archived: options.includeArchived,
|
|
22103
|
+
include_quarantined: options.includeQuarantined,
|
|
22104
|
+
include_superseded: options.includeSuperseded
|
|
22105
|
+
};
|
|
22106
|
+
}
|
|
22107
|
+
function hidden(memory, options) {
|
|
22108
|
+
if (memory.trust_tier === "quarantined") return true;
|
|
22109
|
+
if (options.includeDeleted) return false;
|
|
22110
|
+
return !!memory.is_deleted || memory.archived_at !== void 0 && memory.archived_at !== null || !!memory.superseded_by;
|
|
22111
|
+
}
|
|
22112
|
+
function subscriptionKey({ memory, version }, options) {
|
|
22113
|
+
if (hidden(memory, options)) return void 0;
|
|
22114
|
+
if (options.includeDeleted) return String(!!memory.is_deleted);
|
|
22115
|
+
return JSON.stringify([
|
|
22116
|
+
options.embeddings ? version : null,
|
|
22117
|
+
memory.content,
|
|
22118
|
+
memory.scope,
|
|
22119
|
+
memory.updated_at,
|
|
22120
|
+
memory.fact_type,
|
|
22121
|
+
memory.event_time_start,
|
|
22122
|
+
memory.event_time_end,
|
|
22123
|
+
memory.event_time_kind,
|
|
22124
|
+
memory.trust_tier,
|
|
22125
|
+
memory.visibility,
|
|
22126
|
+
memory.published_at,
|
|
22127
|
+
memory.geohash,
|
|
22128
|
+
memory.topics,
|
|
22129
|
+
memory.topics_user_managed,
|
|
22130
|
+
memory.media,
|
|
22131
|
+
memory.source
|
|
22132
|
+
]);
|
|
22133
|
+
}
|
|
22134
|
+
function topicInputs(topics, source) {
|
|
22135
|
+
return topics.flatMap((topic) => {
|
|
22136
|
+
const name = (typeof topic === "string" ? topic : topic.name).trim();
|
|
22137
|
+
const kind = typeof topic === "string" ? void 0 : topic.kind;
|
|
22138
|
+
return name ? [{ name, ...kind && { kind }, source }] : [];
|
|
22139
|
+
});
|
|
22140
|
+
}
|
|
22141
|
+
function mergeTopics(existing, added) {
|
|
22142
|
+
const byName = /* @__PURE__ */ new Map();
|
|
22143
|
+
for (const topic of [...existing, ...added]) {
|
|
22144
|
+
const key = normalizeEntityName(topic.name);
|
|
22145
|
+
if (!byName.has(key)) byName.set(key, topic);
|
|
22146
|
+
}
|
|
22147
|
+
return [...byName.values()];
|
|
22148
|
+
}
|
|
22149
|
+
function canonicalTopics(row) {
|
|
22150
|
+
return new Set((parseTopics(row.topics) ?? []).map((topic) => normalizeEntityName(topic.name)));
|
|
22151
|
+
}
|
|
22152
|
+
function createRemoteMemoryStore(options) {
|
|
22153
|
+
const { persistence, embeddingOptions } = options;
|
|
22154
|
+
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
22155
|
+
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
22156
|
+
const pipeline = createRemoteMemoryPipeline(options);
|
|
22157
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
22158
|
+
const seen = /* @__PURE__ */ new Map();
|
|
22159
|
+
let timer;
|
|
22160
|
+
const notify = (change, records = []) => {
|
|
22161
|
+
if (timer) for (const record2 of records) seen.set(record2.memory.memory_id, record2);
|
|
22162
|
+
for (const subscriber of [...subscribers])
|
|
22163
|
+
if (relevant(change, subscriber.options)) safely(subscriber.onChange);
|
|
22164
|
+
};
|
|
22165
|
+
const enumerate = async (filters, max = Infinity) => {
|
|
22166
|
+
const records = [];
|
|
22167
|
+
let cursor2;
|
|
22168
|
+
do {
|
|
22169
|
+
const page = await persistence.query({
|
|
22170
|
+
...filters,
|
|
22171
|
+
limit: Math.min(200, Math.max(1, max - records.length)),
|
|
22172
|
+
...cursor2 && { cursor: cursor2 }
|
|
22173
|
+
});
|
|
22174
|
+
warnFailed(page.failed);
|
|
22175
|
+
records.push(...page.items);
|
|
22176
|
+
cursor2 = page.next_cursor;
|
|
22177
|
+
} while (cursor2 && records.length < max);
|
|
22178
|
+
return records.slice(0, max);
|
|
22179
|
+
};
|
|
22180
|
+
const enumerateIds = async (ids, filters) => (await Promise.all(
|
|
22181
|
+
chunks([...new Set(ids)], MAX_QUERY_IDS).map(
|
|
22182
|
+
(memory_ids) => enumerate({ ...filters, memory_ids })
|
|
22183
|
+
)
|
|
22184
|
+
)).flat();
|
|
22185
|
+
const queues = /* @__PURE__ */ new Map();
|
|
22186
|
+
const serialized = (id, task) => {
|
|
22187
|
+
const run = (queues.get(id) ?? Promise.resolve()).then(task, task);
|
|
22188
|
+
const settled = run.catch(() => void 0);
|
|
22189
|
+
queues.set(id, settled);
|
|
22190
|
+
void settled.then(() => {
|
|
22191
|
+
if (queues.get(id) === settled) queues.delete(id);
|
|
22192
|
+
});
|
|
22193
|
+
return run;
|
|
22194
|
+
};
|
|
22195
|
+
const live = async (id) => {
|
|
22196
|
+
const record2 = await persistence.get(id);
|
|
22197
|
+
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
22198
|
+
};
|
|
22199
|
+
const mutate = async (id, change, edit) => serialized(id, async () => {
|
|
22200
|
+
const record2 = await live(id);
|
|
22201
|
+
if (!record2) return null;
|
|
22202
|
+
const next = edit(structuredClone(record2.memory));
|
|
22203
|
+
if (!next) return null;
|
|
22204
|
+
const saved = await persistence.put(next, record2);
|
|
22205
|
+
notify(change, [saved]);
|
|
22206
|
+
return saved;
|
|
22207
|
+
});
|
|
22208
|
+
const embedInBackground = ({ memory: { memory_id: id, content } }) => {
|
|
22209
|
+
generateEmbedding(content, embeddingOptions).then(
|
|
22210
|
+
(vector) => serialized(id, async () => {
|
|
22211
|
+
const current = await live(id);
|
|
22212
|
+
if (!current || current.memory.content !== content || current.memory.embedding?.length)
|
|
22213
|
+
return;
|
|
22214
|
+
const saved = await persistence.put(
|
|
22215
|
+
{ ...current.memory, embedding: storedVector(vector), embedding_model: model },
|
|
22216
|
+
current
|
|
22217
|
+
);
|
|
22218
|
+
notify("embedding", [saved]);
|
|
22219
|
+
})
|
|
22220
|
+
).catch((error) => {
|
|
22221
|
+
getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
|
|
22222
|
+
});
|
|
22223
|
+
};
|
|
22224
|
+
const newRow = (input) => {
|
|
22225
|
+
const now = Date.now();
|
|
22226
|
+
const scope = input.scope ?? "private";
|
|
22227
|
+
return {
|
|
22228
|
+
memory_id: uuidv76(),
|
|
22229
|
+
content: input.content,
|
|
22230
|
+
scope,
|
|
22231
|
+
level: levelFromScope(scope),
|
|
22232
|
+
created_at: now,
|
|
22233
|
+
updated_at: now,
|
|
22234
|
+
is_deleted: false,
|
|
22235
|
+
...input.embedding !== void 0 && {
|
|
22236
|
+
embedding: storedVector(JSON.parse(input.embedding)),
|
|
22237
|
+
embedding_model: input.embeddingModel ?? model
|
|
22238
|
+
},
|
|
22239
|
+
proof_count: 1,
|
|
22240
|
+
source: "manual",
|
|
22241
|
+
...input.eventTime && {
|
|
22242
|
+
event_time_start: input.eventTime.start ?? void 0,
|
|
22243
|
+
event_time_end: input.eventTime.end ?? void 0,
|
|
22244
|
+
event_time_kind: input.eventTime.kind ?? void 0
|
|
22245
|
+
},
|
|
22246
|
+
fact_type: input.factType,
|
|
22247
|
+
geohash: input.geohash,
|
|
22248
|
+
visibility: "private",
|
|
22249
|
+
twin_opt_in: false
|
|
22250
|
+
};
|
|
22251
|
+
};
|
|
22252
|
+
const created = (records, inputs) => {
|
|
22253
|
+
records.forEach((record2, i) => {
|
|
22254
|
+
if (inputs[i].embedding === void 0) embedInBackground(record2);
|
|
22255
|
+
});
|
|
22256
|
+
notify("membership", records);
|
|
22257
|
+
return records.map((record2) => stored(record2.memory));
|
|
22258
|
+
};
|
|
22259
|
+
const asStored = (record2) => record2 ? stored(record2.memory) : null;
|
|
22260
|
+
const everyState = {
|
|
22261
|
+
include_deleted: true,
|
|
22262
|
+
include_archived: true,
|
|
22263
|
+
include_quarantined: true,
|
|
22264
|
+
include_superseded: true
|
|
22265
|
+
};
|
|
22266
|
+
const changesSince = async (cursor2, pending2) => {
|
|
22267
|
+
const records = [];
|
|
22268
|
+
const failed = /* @__PURE__ */ new Set();
|
|
22269
|
+
const collect = (page) => {
|
|
22270
|
+
warnFailed(page.failed);
|
|
22271
|
+
records.push(...page.items);
|
|
22272
|
+
for (const failure of page.failed) failed.add(failure.memory_id);
|
|
22273
|
+
};
|
|
22274
|
+
let resume = cursor2;
|
|
22275
|
+
let next;
|
|
22276
|
+
do {
|
|
22277
|
+
const page = await persistence.query({
|
|
22278
|
+
...everyState,
|
|
22279
|
+
order: "changed",
|
|
22280
|
+
limit: 200,
|
|
22281
|
+
...(next ?? resume) && { cursor: next ?? resume }
|
|
22282
|
+
});
|
|
22283
|
+
collect(page);
|
|
22284
|
+
resume = page.changes_cursor ?? resume;
|
|
22285
|
+
next = page.next_cursor;
|
|
22286
|
+
} while (next);
|
|
22287
|
+
for (const memory_ids of chunks([...pending2], MAX_QUERY_IDS)) {
|
|
22288
|
+
let retry;
|
|
22289
|
+
do {
|
|
22290
|
+
const page = await persistence.query({
|
|
22291
|
+
...everyState,
|
|
22292
|
+
memory_ids,
|
|
22293
|
+
limit: 200,
|
|
22294
|
+
...retry && { cursor: retry }
|
|
22295
|
+
});
|
|
22296
|
+
collect(page);
|
|
22297
|
+
retry = page.next_cursor;
|
|
22298
|
+
} while (retry);
|
|
22299
|
+
}
|
|
22300
|
+
return { records, resume, failed };
|
|
22301
|
+
};
|
|
22302
|
+
let generation = 0;
|
|
22303
|
+
let ready = false;
|
|
22304
|
+
let cursor;
|
|
22305
|
+
let pending = /* @__PURE__ */ new Set();
|
|
22306
|
+
let polling = false;
|
|
22307
|
+
const poll = () => {
|
|
22308
|
+
if (polling) return;
|
|
22309
|
+
polling = true;
|
|
22310
|
+
const current = generation;
|
|
22311
|
+
changesSince(cursor, pending).then(({ records, resume, failed }) => {
|
|
22312
|
+
if (current !== generation) return;
|
|
22313
|
+
const changed = /* @__PURE__ */ new Set();
|
|
22314
|
+
for (const record2 of records) {
|
|
22315
|
+
const id = record2.memory.memory_id;
|
|
22316
|
+
const previous = seen.get(id);
|
|
22317
|
+
seen.set(id, record2);
|
|
22318
|
+
if (!ready) continue;
|
|
22319
|
+
for (const subscriber of subscribers) {
|
|
22320
|
+
const before = previous && subscriptionKey(previous, subscriber.options);
|
|
22321
|
+
if (before !== subscriptionKey(record2, subscriber.options)) changed.add(subscriber);
|
|
22322
|
+
}
|
|
22323
|
+
}
|
|
22324
|
+
ready = true;
|
|
22325
|
+
cursor = resume;
|
|
22326
|
+
pending = failed;
|
|
22327
|
+
for (const subscriber of changed)
|
|
22328
|
+
if (subscribers.has(subscriber)) safely(subscriber.onChange);
|
|
22329
|
+
}).catch((error) => {
|
|
22330
|
+
getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
|
|
22331
|
+
}).finally(() => {
|
|
22332
|
+
polling = false;
|
|
22333
|
+
});
|
|
22334
|
+
};
|
|
22335
|
+
return {
|
|
22336
|
+
list: async (listOptions = {}) => {
|
|
22337
|
+
const order = listOptions.since ? "updated" : "created";
|
|
22338
|
+
const filters = {
|
|
22339
|
+
...stateFilters(listOptions),
|
|
22340
|
+
include_embeddings: true,
|
|
22341
|
+
order,
|
|
22342
|
+
...listOptions.scopes?.length && { scopes: listOptions.scopes },
|
|
22343
|
+
...listOptions.factTypes?.length && { fact_types: listOptions.factTypes },
|
|
22344
|
+
...listOptions.visibility?.length && { visibility: listOptions.visibility },
|
|
22345
|
+
...listOptions.since && { updated_after: listOptions.since.getTime() }
|
|
22346
|
+
};
|
|
22347
|
+
const max = listOptions.limit && listOptions.limit > 0 ? listOptions.limit : Infinity;
|
|
22348
|
+
const variants = bounded(filters, "scopes").flatMap((f) => bounded(f, "fact_types"));
|
|
22349
|
+
if (!listOptions.memoryIds && variants.length === 1)
|
|
22350
|
+
return (await enumerate(filters, max)).map((r) => stored(r.memory));
|
|
22351
|
+
const fetched = await Promise.all(
|
|
22352
|
+
variants.map(
|
|
22353
|
+
(variant) => listOptions.memoryIds ? enumerateIds(listOptions.memoryIds, variant) : enumerate(variant, max)
|
|
22354
|
+
)
|
|
22355
|
+
);
|
|
22356
|
+
const rows = [...new Map(fetched.flat().map((r) => [r.memory.memory_id, r])).values()].map((record2) => stored(record2.memory)).sort(
|
|
22357
|
+
(a, b) => order === "updated" ? b.updatedAt.getTime() - a.updatedAt.getTime() || (a.uniqueId < b.uniqueId ? 1 : -1) : b.createdAt.getTime() - a.createdAt.getTime() || (a.uniqueId < b.uniqueId ? 1 : -1)
|
|
22358
|
+
);
|
|
22359
|
+
return rows.slice(0, max);
|
|
22360
|
+
},
|
|
22361
|
+
get: async (id) => asStored(await live(id)),
|
|
22362
|
+
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
22363
|
+
(record2) => stored(record2.memory)
|
|
22364
|
+
),
|
|
22365
|
+
memoriesByTopics: async (names) => {
|
|
22366
|
+
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
22367
|
+
const out = /* @__PURE__ */ new Map();
|
|
22368
|
+
const pages = await Promise.all(
|
|
22369
|
+
chunks([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
22370
|
+
);
|
|
22371
|
+
for (const { memory } of pages.flat()) {
|
|
22372
|
+
const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
|
|
22373
|
+
if (matched.length) out.set(memory.memory_id, new Set(matched));
|
|
22374
|
+
}
|
|
22375
|
+
return out;
|
|
22376
|
+
},
|
|
22377
|
+
topicsByMemories: async (memoryIds) => {
|
|
22378
|
+
const out = /* @__PURE__ */ new Map();
|
|
22379
|
+
for (const { memory } of await enumerateIds(memoryIds, {
|
|
22380
|
+
include_archived: true,
|
|
22381
|
+
include_superseded: true,
|
|
22382
|
+
include_quarantined: true
|
|
22383
|
+
})) {
|
|
22384
|
+
const topics = canonicalTopics(memory);
|
|
22385
|
+
if (topics.size) out.set(memory.memory_id, topics);
|
|
22386
|
+
}
|
|
22387
|
+
return out;
|
|
22388
|
+
},
|
|
22389
|
+
create: async (input) => {
|
|
22390
|
+
const record2 = await persistence.put(newRow(input), 0);
|
|
22391
|
+
return created([record2], [input])[0];
|
|
22392
|
+
},
|
|
22393
|
+
createMany: async (inputs) => {
|
|
22394
|
+
const out = [];
|
|
22395
|
+
for (const batch of chunks(inputs, MAX_BATCH)) {
|
|
22396
|
+
let records;
|
|
22397
|
+
try {
|
|
22398
|
+
records = await persistence.putMany(
|
|
22399
|
+
batch.map((input) => ({ memory: newRow(input), expectedVersion: 0 }))
|
|
22400
|
+
);
|
|
22401
|
+
} catch (error) {
|
|
22402
|
+
if (out.length === 0) throw error;
|
|
22403
|
+
throw new RemoteMemoryPartialCreateError(out, error);
|
|
22404
|
+
}
|
|
22405
|
+
out.push(...created(records, batch));
|
|
22406
|
+
}
|
|
22407
|
+
return out;
|
|
22408
|
+
},
|
|
22409
|
+
update: async (id, patch) => {
|
|
22410
|
+
const saved = await mutate(id, "edit", (memory) => {
|
|
22411
|
+
if (memory.superseded_by) return null;
|
|
22412
|
+
memory.content = patch.content;
|
|
22413
|
+
memory.updated_at = Date.now();
|
|
22414
|
+
if (patch.scope !== void 0) {
|
|
22415
|
+
memory.level = levelForScopeChange(
|
|
22416
|
+
{ level: memory.level, scope: memory.scope },
|
|
22417
|
+
patch.scope
|
|
22418
|
+
);
|
|
22419
|
+
memory.scope = patch.scope;
|
|
22420
|
+
}
|
|
22421
|
+
if (patch.factType !== void 0) memory.fact_type = patch.factType ?? void 0;
|
|
22422
|
+
if (patch.eventTime !== void 0) {
|
|
22423
|
+
memory.event_time_start = patch.eventTime?.start ?? void 0;
|
|
22424
|
+
memory.event_time_end = patch.eventTime?.end ?? void 0;
|
|
22425
|
+
memory.event_time_kind = patch.eventTime?.kind ?? void 0;
|
|
22426
|
+
}
|
|
22427
|
+
if (patch.embedding === void 0 || patch.embedding === null) {
|
|
22428
|
+
memory.embedding = [];
|
|
22429
|
+
delete memory.embedding_model;
|
|
22430
|
+
} else {
|
|
22431
|
+
memory.embedding = storedVector(JSON.parse(patch.embedding));
|
|
22432
|
+
memory.embedding_model = patch.embeddingModel ?? model;
|
|
22433
|
+
}
|
|
22434
|
+
return memory;
|
|
22435
|
+
});
|
|
22436
|
+
if (saved && patch.embedding === void 0) embedInBackground(saved);
|
|
22437
|
+
return asStored(saved);
|
|
22438
|
+
},
|
|
22439
|
+
delete: async (id) => !!await mutate(id, "membership", (memory) => ({ ...memory, is_deleted: true })),
|
|
22440
|
+
supersede: async (id, supersededById) => {
|
|
22441
|
+
if (id === supersededById) return false;
|
|
22442
|
+
const [first, second] = [id, supersededById].sort();
|
|
22443
|
+
return serialized(
|
|
22444
|
+
first,
|
|
22445
|
+
() => serialized(second, async () => {
|
|
22446
|
+
const [old, next] = await Promise.all([live(id), live(supersededById)]);
|
|
22447
|
+
if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
|
|
22448
|
+
if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
|
|
22449
|
+
const saved = await persistence.putMany([
|
|
22450
|
+
{
|
|
22451
|
+
memory: { ...old.memory, superseded_by: supersededById, superseded_at: Date.now() },
|
|
22452
|
+
expectedVersion: old
|
|
22453
|
+
},
|
|
22454
|
+
{ memory: next.memory, expectedVersion: next }
|
|
22455
|
+
]);
|
|
22456
|
+
notify("membership", saved);
|
|
22457
|
+
return true;
|
|
22458
|
+
})
|
|
22459
|
+
);
|
|
22460
|
+
},
|
|
22461
|
+
archive: async (id) => !!await mutate(
|
|
22462
|
+
id,
|
|
22463
|
+
"edit",
|
|
22464
|
+
(memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
|
|
22465
|
+
),
|
|
22466
|
+
restore: (id) => serialized(id, async () => {
|
|
22467
|
+
const record2 = await live(id);
|
|
22468
|
+
if (!record2) return false;
|
|
22469
|
+
if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
|
|
22470
|
+
return true;
|
|
22471
|
+
const { archived_at: _archivedAt, ...memory } = record2.memory;
|
|
22472
|
+
notify("edit", [await persistence.put(memory, record2)]);
|
|
22473
|
+
return true;
|
|
22474
|
+
}),
|
|
22475
|
+
setTopics: async (memoryId, topics) => asStored(
|
|
22476
|
+
await mutate(memoryId, "edit", (memory) => ({
|
|
22477
|
+
...memory,
|
|
22478
|
+
topics: serializeTopics(mergeTopics([], topicInputs(topics, "user"))),
|
|
22479
|
+
topics_user_managed: true,
|
|
22480
|
+
topics_updated_at: Date.now()
|
|
22481
|
+
}))
|
|
22482
|
+
),
|
|
22483
|
+
addTopics: async (memoryId, topics) => {
|
|
22484
|
+
const added = topicInputs(topics, "auto");
|
|
22485
|
+
const saved = await mutate(memoryId, "edit", (memory) => ({
|
|
22486
|
+
...memory,
|
|
22487
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
22488
|
+
topics_updated_at: Date.now()
|
|
22489
|
+
}));
|
|
22490
|
+
if (!saved) return [];
|
|
22491
|
+
const now = /* @__PURE__ */ new Date();
|
|
22492
|
+
return mergeTopics([], added).map(
|
|
22493
|
+
(topic) => ({
|
|
22494
|
+
uniqueId: normalizeEntityName(topic.name),
|
|
22495
|
+
canonicalName: normalizeEntityName(topic.name),
|
|
22496
|
+
kind: topic.kind ?? null,
|
|
22497
|
+
createdAt: now,
|
|
22498
|
+
updatedAt: now
|
|
22499
|
+
})
|
|
22500
|
+
);
|
|
22501
|
+
},
|
|
22502
|
+
setVisibility: async (id, visibility, visibilityOptions) => asStored(
|
|
22503
|
+
await mutate(id, "edit", (memory) => {
|
|
22504
|
+
memory.visibility = visibility;
|
|
22505
|
+
if (visibility === "private") delete memory.published_at;
|
|
22506
|
+
else memory.published_at ?? (memory.published_at = Date.now());
|
|
22507
|
+
if (visibilityOptions?.twinOptIn !== void 0)
|
|
22508
|
+
memory.twin_opt_in = visibilityOptions.twinOptIn;
|
|
22509
|
+
return memory;
|
|
22510
|
+
})
|
|
22511
|
+
),
|
|
22512
|
+
recall: (query, recallOptions) => pipeline.recall(query, recallOptions),
|
|
22513
|
+
retain: async (content, retainOptions) => {
|
|
22514
|
+
const result = await pipeline.retain(content, retainOptions);
|
|
22515
|
+
if (result.action === "create" || result.action === "supersede") notify("membership");
|
|
22516
|
+
else if (result.action === "update" || result.action === "merge") notify("edit");
|
|
22517
|
+
return result;
|
|
22518
|
+
},
|
|
22519
|
+
subscribe: (onChange, subscribeOptions = {}) => {
|
|
22520
|
+
const subscriber = { onChange, options: subscribeOptions };
|
|
22521
|
+
subscribers.add(subscriber);
|
|
22522
|
+
if (pollIntervalMs > 0 && !timer) {
|
|
22523
|
+
timer = setInterval(poll, pollIntervalMs);
|
|
22524
|
+
poll();
|
|
22525
|
+
}
|
|
22526
|
+
return () => {
|
|
22527
|
+
subscribers.delete(subscriber);
|
|
22528
|
+
if (subscribers.size || !timer) return;
|
|
22529
|
+
clearInterval(timer);
|
|
22530
|
+
timer = void 0;
|
|
22531
|
+
generation++;
|
|
22532
|
+
seen.clear();
|
|
22533
|
+
ready = false;
|
|
22534
|
+
cursor = void 0;
|
|
22535
|
+
pending = /* @__PURE__ */ new Set();
|
|
22536
|
+
};
|
|
22537
|
+
}
|
|
22538
|
+
};
|
|
22539
|
+
}
|
|
22540
|
+
|
|
21754
22541
|
// src/lib/memory/synthesizeProfile.ts
|
|
21755
22542
|
var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
|
|
21756
22543
|
var DEFAULT_FACET_RECALL_LIMIT = 20;
|
|
@@ -35729,7 +36516,11 @@ export {
|
|
|
35729
36516
|
LoggerProvider,
|
|
35730
36517
|
MAX_HOPS,
|
|
35731
36518
|
MEDIUM_TTL_MS,
|
|
36519
|
+
MEMORY_KINDS,
|
|
36520
|
+
MEMORY_LEVELS,
|
|
35732
36521
|
MemoryEntity as MemoryEntityModel,
|
|
36522
|
+
MemoryKeyError,
|
|
36523
|
+
MemoryLevelError,
|
|
35733
36524
|
NEVER_TTL_MS,
|
|
35734
36525
|
NODE_BUDGET,
|
|
35735
36526
|
PAST_EVENT_GRACE_MS,
|
|
@@ -35743,6 +36534,7 @@ export {
|
|
|
35743
36534
|
RECALL_MAX_LIMIT,
|
|
35744
36535
|
RECALL_TOOL_NAME,
|
|
35745
36536
|
RemoteMemoryError,
|
|
36537
|
+
RemoteMemoryPartialCreateError,
|
|
35746
36538
|
RerankerUnavailableError,
|
|
35747
36539
|
SDK_SCHEMA_VERSION,
|
|
35748
36540
|
SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -35836,6 +36628,7 @@ export {
|
|
|
35836
36628
|
createRecallTool,
|
|
35837
36629
|
createRemoteMemoryPersistence,
|
|
35838
36630
|
createRemoteMemoryPipeline,
|
|
36631
|
+
createRemoteMemoryStore,
|
|
35839
36632
|
createSavedToolOp,
|
|
35840
36633
|
createServerToolsFilter,
|
|
35841
36634
|
createStockPricePreProcessor,
|
|
@@ -35867,6 +36660,7 @@ export {
|
|
|
35867
36660
|
deleteVaultMemoryOp,
|
|
35868
36661
|
dequantizeEmbedding,
|
|
35869
36662
|
deriveKeyFromSignatureBytes,
|
|
36663
|
+
deriveMemoryKeyRing,
|
|
35870
36664
|
eagerEmbedContent,
|
|
35871
36665
|
embedAllMessages,
|
|
35872
36666
|
embedMessage,
|
|
@@ -36006,6 +36800,7 @@ export {
|
|
|
36006
36800
|
linkMemoryEntitiesOp,
|
|
36007
36801
|
maskScopedEmbeddingCache,
|
|
36008
36802
|
mediaToStored,
|
|
36803
|
+
memoryCipher,
|
|
36009
36804
|
migrateCalendarToken,
|
|
36010
36805
|
migrateDisplayResult,
|
|
36011
36806
|
migrateDriveToken,
|
|
@@ -36027,6 +36822,7 @@ export {
|
|
|
36027
36822
|
rankProfileCandidates,
|
|
36028
36823
|
readEncryptedFile,
|
|
36029
36824
|
recall,
|
|
36825
|
+
reencryptMemoryField,
|
|
36030
36826
|
reflect,
|
|
36031
36827
|
refreshCalendarToken,
|
|
36032
36828
|
refreshDriveToken,
|