@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.cjs
CHANGED
|
@@ -1424,7 +1424,11 @@ __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
|
+
MemoryKeyError: () => MemoryKeyError,
|
|
1431
|
+
MemoryLevelError: () => MemoryLevelError,
|
|
1428
1432
|
NEVER_TTL_MS: () => NEVER_TTL_MS,
|
|
1429
1433
|
NODE_BUDGET: () => NODE_BUDGET,
|
|
1430
1434
|
PAST_EVENT_GRACE_MS: () => PAST_EVENT_GRACE_MS,
|
|
@@ -1438,6 +1442,7 @@ __export(index_exports, {
|
|
|
1438
1442
|
RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
|
|
1439
1443
|
RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
|
|
1440
1444
|
RemoteMemoryError: () => RemoteMemoryError,
|
|
1445
|
+
RemoteMemoryPartialCreateError: () => RemoteMemoryPartialCreateError,
|
|
1441
1446
|
RerankerUnavailableError: () => RerankerUnavailableError,
|
|
1442
1447
|
SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
|
|
1443
1448
|
SERVER_TOOL_DEPENDENCY_SETS: () => SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -1531,6 +1536,7 @@ __export(index_exports, {
|
|
|
1531
1536
|
createRecallTool: () => createRecallTool,
|
|
1532
1537
|
createRemoteMemoryPersistence: () => createRemoteMemoryPersistence,
|
|
1533
1538
|
createRemoteMemoryPipeline: () => createRemoteMemoryPipeline,
|
|
1539
|
+
createRemoteMemoryStore: () => createRemoteMemoryStore,
|
|
1534
1540
|
createSavedToolOp: () => createSavedToolOp,
|
|
1535
1541
|
createServerToolsFilter: () => createServerToolsFilter,
|
|
1536
1542
|
createStockPricePreProcessor: () => createStockPricePreProcessor,
|
|
@@ -1562,6 +1568,7 @@ __export(index_exports, {
|
|
|
1562
1568
|
deleteVaultMemoryOp: () => deleteVaultMemoryOp,
|
|
1563
1569
|
dequantizeEmbedding: () => dequantizeEmbedding,
|
|
1564
1570
|
deriveKeyFromSignatureBytes: () => deriveKeyFromSignatureBytes,
|
|
1571
|
+
deriveMemoryKeyRing: () => deriveMemoryKeyRing,
|
|
1565
1572
|
eagerEmbedContent: () => eagerEmbedContent,
|
|
1566
1573
|
embedAllMessages: () => embedAllMessages,
|
|
1567
1574
|
embedMessage: () => embedMessage,
|
|
@@ -1701,6 +1708,7 @@ __export(index_exports, {
|
|
|
1701
1708
|
linkMemoryEntitiesOp: () => linkMemoryEntitiesOp,
|
|
1702
1709
|
maskScopedEmbeddingCache: () => maskScopedEmbeddingCache,
|
|
1703
1710
|
mediaToStored: () => mediaToStored,
|
|
1711
|
+
memoryCipher: () => memoryCipher,
|
|
1704
1712
|
migrateCalendarToken: () => migrateCalendarToken,
|
|
1705
1713
|
migrateDisplayResult: () => migrateDisplayResult,
|
|
1706
1714
|
migrateDriveToken: () => migrateDriveToken,
|
|
@@ -1722,6 +1730,7 @@ __export(index_exports, {
|
|
|
1722
1730
|
rankProfileCandidates: () => rankProfileCandidates,
|
|
1723
1731
|
readEncryptedFile: () => readEncryptedFile,
|
|
1724
1732
|
recall: () => recall,
|
|
1733
|
+
reencryptMemoryField: () => reencryptMemoryField,
|
|
1725
1734
|
reflect: () => reflect,
|
|
1726
1735
|
refreshCalendarToken: () => refreshCalendarToken,
|
|
1727
1736
|
refreshDriveToken: () => refreshDriveToken,
|
|
@@ -1901,9 +1910,9 @@ function createSseClient({
|
|
|
1901
1910
|
if (done) break;
|
|
1902
1911
|
buffer += value;
|
|
1903
1912
|
buffer = buffer.replace(/\r\n?/g, "\n");
|
|
1904
|
-
const
|
|
1905
|
-
buffer =
|
|
1906
|
-
for (const chunk of
|
|
1913
|
+
const chunks2 = buffer.split("\n\n");
|
|
1914
|
+
buffer = chunks2.pop() ?? "";
|
|
1915
|
+
for (const chunk of chunks2) {
|
|
1907
1916
|
const lines = chunk.split("\n");
|
|
1908
1917
|
const dataLines = [];
|
|
1909
1918
|
let eventName;
|
|
@@ -6555,14 +6564,14 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
|
|
|
6555
6564
|
});
|
|
6556
6565
|
return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
6557
6566
|
}
|
|
6558
|
-
async function updateMessageChunksOp(ctx, uniqueId,
|
|
6567
|
+
async function updateMessageChunksOp(ctx, uniqueId, chunks2, embeddingModel) {
|
|
6559
6568
|
let message;
|
|
6560
6569
|
try {
|
|
6561
6570
|
message = await ctx.messagesCollection.find(uniqueId);
|
|
6562
6571
|
} catch {
|
|
6563
6572
|
return null;
|
|
6564
6573
|
}
|
|
6565
|
-
const storedChunks =
|
|
6574
|
+
const storedChunks = chunks2.map(({ text: _text, ...rest }) => rest);
|
|
6566
6575
|
await ctx.database.write(async () => {
|
|
6567
6576
|
await message.update((msg) => {
|
|
6568
6577
|
msg._setRaw("chunks", JSON.stringify(storedChunks));
|
|
@@ -6606,12 +6615,12 @@ async function stripLegacyChunkTextOp(ctx) {
|
|
|
6606
6615
|
const messages = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(changedIds))).fetch();
|
|
6607
6616
|
const updates = messages.flatMap((message) => {
|
|
6608
6617
|
const raw = message._raw;
|
|
6609
|
-
const
|
|
6610
|
-
if (!
|
|
6618
|
+
const chunks2 = chunksWithoutText(raw.chunks);
|
|
6619
|
+
if (!chunks2) return [];
|
|
6611
6620
|
const updatedAt = raw.updated_at;
|
|
6612
6621
|
return [
|
|
6613
6622
|
message.prepareUpdate((msg) => {
|
|
6614
|
-
msg._setRaw("chunks", JSON.stringify(
|
|
6623
|
+
msg._setRaw("chunks", JSON.stringify(chunks2));
|
|
6615
6624
|
msg._setRaw("updated_at", updatedAt);
|
|
6616
6625
|
})
|
|
6617
6626
|
];
|
|
@@ -6821,15 +6830,15 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
6821
6830
|
}
|
|
6822
6831
|
continue;
|
|
6823
6832
|
}
|
|
6824
|
-
const
|
|
6825
|
-
if (
|
|
6826
|
-
const vectors =
|
|
6833
|
+
const chunks2 = await readRawJsonField(message, "chunks", ctx.walletAddress);
|
|
6834
|
+
if (chunks2 && chunks2.length > 0) {
|
|
6835
|
+
const vectors = chunks2.map(
|
|
6827
6836
|
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
6828
6837
|
unreadableVectors++;
|
|
6829
6838
|
})
|
|
6830
6839
|
);
|
|
6831
6840
|
chunkCache?.set(message.id, { version, chunks: vectors });
|
|
6832
|
-
for (let ci = 0; ci <
|
|
6841
|
+
for (let ci = 0; ci < chunks2.length; ci++) {
|
|
6833
6842
|
const vec = vectors[ci];
|
|
6834
6843
|
if (vec.length === 0) continue;
|
|
6835
6844
|
const similarity = cosineSimilarity(queryVector, vec);
|
|
@@ -6837,7 +6846,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
6837
6846
|
candidates.push({
|
|
6838
6847
|
message,
|
|
6839
6848
|
similarity,
|
|
6840
|
-
chunkTextSource: { kind: "chunk", chunk:
|
|
6849
|
+
chunkTextSource: { kind: "chunk", chunk: chunks2[ci], siblings: chunks2 }
|
|
6841
6850
|
});
|
|
6842
6851
|
}
|
|
6843
6852
|
}
|
|
@@ -7017,7 +7026,7 @@ function chunkText(text12, options) {
|
|
|
7017
7026
|
];
|
|
7018
7027
|
}
|
|
7019
7028
|
const sentences = splitIntoSentences(text12);
|
|
7020
|
-
const
|
|
7029
|
+
const chunks2 = [];
|
|
7021
7030
|
let currentChunkSentences = [];
|
|
7022
7031
|
let currentChunkStart = 0;
|
|
7023
7032
|
let currentOffset = 0;
|
|
@@ -7031,7 +7040,7 @@ function chunkText(text12, options) {
|
|
|
7031
7040
|
if (sentence.length > chunkSize) {
|
|
7032
7041
|
if (currentChunkSentences.length > 0) {
|
|
7033
7042
|
const chunkText2 = currentChunkSentences.join(" ");
|
|
7034
|
-
|
|
7043
|
+
chunks2.push({
|
|
7035
7044
|
text: chunkText2,
|
|
7036
7045
|
startOffset: currentChunkStart,
|
|
7037
7046
|
endOffset: currentOffset
|
|
@@ -7042,7 +7051,7 @@ function chunkText(text12, options) {
|
|
|
7042
7051
|
const chunkEnd = Math.min(j + chunkSize, sentence.length);
|
|
7043
7052
|
const chunk = sentence.slice(j, chunkEnd);
|
|
7044
7053
|
if (chunk.length >= minChunkSize) {
|
|
7045
|
-
|
|
7054
|
+
chunks2.push({
|
|
7046
7055
|
text: chunk,
|
|
7047
7056
|
startOffset: sentenceStart + j,
|
|
7048
7057
|
endOffset: sentenceStart + chunkEnd
|
|
@@ -7056,7 +7065,7 @@ function chunkText(text12, options) {
|
|
|
7056
7065
|
const currentText = currentChunkSentences.join(" ");
|
|
7057
7066
|
const potentialLength = currentText.length + (currentText ? 1 : 0) + sentence.length;
|
|
7058
7067
|
if (potentialLength > chunkSize && currentChunkSentences.length > 0) {
|
|
7059
|
-
|
|
7068
|
+
chunks2.push({
|
|
7060
7069
|
text: currentText,
|
|
7061
7070
|
startOffset: currentChunkStart,
|
|
7062
7071
|
endOffset: currentOffset
|
|
@@ -7087,14 +7096,14 @@ function chunkText(text12, options) {
|
|
|
7087
7096
|
if (currentChunkSentences.length > 0) {
|
|
7088
7097
|
const chunkText2 = currentChunkSentences.join(" ");
|
|
7089
7098
|
if (chunkText2.length >= minChunkSize) {
|
|
7090
|
-
|
|
7099
|
+
chunks2.push({
|
|
7091
7100
|
text: chunkText2,
|
|
7092
7101
|
startOffset: currentChunkStart,
|
|
7093
7102
|
endOffset: text12.length
|
|
7094
7103
|
});
|
|
7095
7104
|
}
|
|
7096
7105
|
}
|
|
7097
|
-
if (
|
|
7106
|
+
if (chunks2.length === 0) {
|
|
7098
7107
|
const trimmedText = text12.trim();
|
|
7099
7108
|
if (trimmedText.length > 0) {
|
|
7100
7109
|
return [
|
|
@@ -7106,7 +7115,7 @@ function chunkText(text12, options) {
|
|
|
7106
7115
|
];
|
|
7107
7116
|
}
|
|
7108
7117
|
}
|
|
7109
|
-
return
|
|
7118
|
+
return chunks2;
|
|
7110
7119
|
}
|
|
7111
7120
|
function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
|
|
7112
7121
|
return content.length > chunkSize;
|
|
@@ -7325,18 +7334,18 @@ async function embedMany(texts, options, outer) {
|
|
|
7325
7334
|
outer
|
|
7326
7335
|
);
|
|
7327
7336
|
} else {
|
|
7328
|
-
const
|
|
7337
|
+
const chunks2 = [];
|
|
7329
7338
|
for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
|
|
7330
|
-
|
|
7339
|
+
chunks2.push(uncachedTexts.slice(i, i + chunkSize));
|
|
7331
7340
|
}
|
|
7332
|
-
const allEmbeddings = new Array(
|
|
7341
|
+
const allEmbeddings = new Array(chunks2.length);
|
|
7333
7342
|
let nextIndex = 0;
|
|
7334
7343
|
const worker = async () => {
|
|
7335
|
-
while (nextIndex <
|
|
7344
|
+
while (nextIndex < chunks2.length) {
|
|
7336
7345
|
if (outer?.aborted) throw outer.reason;
|
|
7337
7346
|
const idx = nextIndex++;
|
|
7338
7347
|
allEmbeddings[idx] = await generateEmbeddingsBatch(
|
|
7339
|
-
|
|
7348
|
+
chunks2[idx],
|
|
7340
7349
|
headers,
|
|
7341
7350
|
baseUrl,
|
|
7342
7351
|
embeddingModel,
|
|
@@ -7348,7 +7357,7 @@ async function embedMany(texts, options, outer) {
|
|
|
7348
7357
|
}
|
|
7349
7358
|
};
|
|
7350
7359
|
const workers = Array.from(
|
|
7351
|
-
{ length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY,
|
|
7360
|
+
{ length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks2.length) },
|
|
7352
7361
|
() => worker()
|
|
7353
7362
|
);
|
|
7354
7363
|
await Promise.all(workers);
|
|
@@ -13155,6 +13164,15 @@ __decorateClass([
|
|
|
13155
13164
|
__decorateClass([
|
|
13156
13165
|
(0, import_decorators6.text)("scope")
|
|
13157
13166
|
], VaultMemory.prototype, "scope", 2);
|
|
13167
|
+
__decorateClass([
|
|
13168
|
+
(0, import_decorators6.field)("kind")
|
|
13169
|
+
], VaultMemory.prototype, "kind", 2);
|
|
13170
|
+
__decorateClass([
|
|
13171
|
+
(0, import_decorators6.field)("kind_value")
|
|
13172
|
+
], VaultMemory.prototype, "kindValue", 2);
|
|
13173
|
+
__decorateClass([
|
|
13174
|
+
(0, import_decorators6.field)("level")
|
|
13175
|
+
], VaultMemory.prototype, "level", 2);
|
|
13158
13176
|
__decorateClass([
|
|
13159
13177
|
(0, import_decorators6.field)("folder_id")
|
|
13160
13178
|
], VaultMemory.prototype, "folderId", 2);
|
|
@@ -13380,7 +13398,7 @@ __decorateClass([
|
|
|
13380
13398
|
], VaultFolder.prototype, "context", 2);
|
|
13381
13399
|
|
|
13382
13400
|
// src/lib/db/schema.ts
|
|
13383
|
-
var SDK_SCHEMA_VERSION =
|
|
13401
|
+
var SDK_SCHEMA_VERSION = 48;
|
|
13384
13402
|
var sdkSchema = (0, import_watermelondb19.appSchema)({
|
|
13385
13403
|
version: SDK_SCHEMA_VERSION,
|
|
13386
13404
|
tables: [
|
|
@@ -13475,6 +13493,9 @@ var sdkSchema = (0, import_watermelondb19.appSchema)({
|
|
|
13475
13493
|
columns: [
|
|
13476
13494
|
{ name: "content", type: "string" },
|
|
13477
13495
|
{ name: "scope", type: "string", isIndexed: true },
|
|
13496
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
13497
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
13498
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true },
|
|
13478
13499
|
{ name: "folder_id", type: "string", isOptional: true, isIndexed: true },
|
|
13479
13500
|
{ name: "created_at", type: "number", isIndexed: true },
|
|
13480
13501
|
{ name: "updated_at", type: "number", isIndexed: true },
|
|
@@ -14151,6 +14172,22 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
|
|
|
14151
14172
|
]
|
|
14152
14173
|
})
|
|
14153
14174
|
]
|
|
14175
|
+
},
|
|
14176
|
+
{
|
|
14177
|
+
toVersion: 48,
|
|
14178
|
+
steps: [
|
|
14179
|
+
(0, import_migrations2.addColumns)({
|
|
14180
|
+
table: "memory_vault",
|
|
14181
|
+
columns: [
|
|
14182
|
+
{ name: "kind", type: "string", isOptional: true, isIndexed: true },
|
|
14183
|
+
{ name: "kind_value", type: "string", isOptional: true },
|
|
14184
|
+
{ name: "level", type: "string", isOptional: true, isIndexed: true }
|
|
14185
|
+
]
|
|
14186
|
+
}),
|
|
14187
|
+
(0, import_migrations2.unsafeExecuteSql)(
|
|
14188
|
+
"UPDATE memory_vault SET level = CASE WHEN scope IN ('shared', 'public') THEN 'matching' ELSE 'private' END WHERE level IS NULL;"
|
|
14189
|
+
)
|
|
14190
|
+
]
|
|
14154
14191
|
}
|
|
14155
14192
|
]
|
|
14156
14193
|
});
|
|
@@ -14674,8 +14711,8 @@ var WatermelonChatStorageAdapter = class {
|
|
|
14674
14711
|
updateMessageEmbedding(uniqueId, vector, embeddingModel) {
|
|
14675
14712
|
return updateMessageEmbeddingOp(this.ctx, uniqueId, vector, embeddingModel);
|
|
14676
14713
|
}
|
|
14677
|
-
updateMessageChunks(uniqueId,
|
|
14678
|
-
return updateMessageChunksOp(this.ctx, uniqueId,
|
|
14714
|
+
updateMessageChunks(uniqueId, chunks2, embeddingModel) {
|
|
14715
|
+
return updateMessageChunksOp(this.ctx, uniqueId, chunks2, embeddingModel);
|
|
14679
14716
|
}
|
|
14680
14717
|
updateMessageError(uniqueId, error) {
|
|
14681
14718
|
return updateMessageErrorOp(this.ctx, uniqueId, error);
|
|
@@ -15292,13 +15329,54 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
15292
15329
|
}
|
|
15293
15330
|
}
|
|
15294
15331
|
const decryptedContent = await decryptField(memory.content, address);
|
|
15332
|
+
const decryptedKindValue = typeof memory.kindValue === "string" ? await decryptField(memory.kindValue, address) : memory.kindValue;
|
|
15295
15333
|
return {
|
|
15296
15334
|
...memory,
|
|
15297
|
-
content: decryptedContent
|
|
15335
|
+
content: decryptedContent,
|
|
15336
|
+
...decryptedKindValue !== void 0 && { kindValue: decryptedKindValue }
|
|
15298
15337
|
};
|
|
15299
15338
|
}
|
|
15300
15339
|
|
|
15301
15340
|
// src/lib/db/memoryVault/types.ts
|
|
15341
|
+
var MEMORY_KINDS = [
|
|
15342
|
+
"display_name",
|
|
15343
|
+
"birth_date",
|
|
15344
|
+
"bio",
|
|
15345
|
+
"occupation",
|
|
15346
|
+
"interest",
|
|
15347
|
+
"gender",
|
|
15348
|
+
"height_cm",
|
|
15349
|
+
"looking_for",
|
|
15350
|
+
"politics",
|
|
15351
|
+
"religion",
|
|
15352
|
+
"ethnicity",
|
|
15353
|
+
"smoking",
|
|
15354
|
+
"drinking",
|
|
15355
|
+
"exercise",
|
|
15356
|
+
"sexuality",
|
|
15357
|
+
"prompt"
|
|
15358
|
+
];
|
|
15359
|
+
var MEMORY_LEVELS = ["private", "matching", "profile"];
|
|
15360
|
+
var MemoryLevelError = class extends Error {
|
|
15361
|
+
constructor(message) {
|
|
15362
|
+
super(message);
|
|
15363
|
+
this.name = "MemoryLevelError";
|
|
15364
|
+
}
|
|
15365
|
+
};
|
|
15366
|
+
var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
|
|
15367
|
+
function levelFromScope(scope) {
|
|
15368
|
+
return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
|
|
15369
|
+
}
|
|
15370
|
+
function scopeForLevel(level) {
|
|
15371
|
+
return level === "private" ? "private" : "shared";
|
|
15372
|
+
}
|
|
15373
|
+
function resolveMemoryLevel(level, scope) {
|
|
15374
|
+
return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
|
|
15375
|
+
}
|
|
15376
|
+
function levelForScopeChange(current, nextScope) {
|
|
15377
|
+
const implied = levelFromScope(nextScope);
|
|
15378
|
+
return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
|
|
15379
|
+
}
|
|
15302
15380
|
function parseMedia(value) {
|
|
15303
15381
|
if (typeof value !== "string" || value === "") return null;
|
|
15304
15382
|
try {
|
|
@@ -15328,6 +15406,56 @@ function visibilityConditions(requested) {
|
|
|
15328
15406
|
if (excluded.length === 0) return [];
|
|
15329
15407
|
return [import_watermelondb23.Q.or(import_watermelondb23.Q.where("visibility", null), import_watermelondb23.Q.where("visibility", import_watermelondb23.Q.notIn(excluded)))];
|
|
15330
15408
|
}
|
|
15409
|
+
function isKinded(record2) {
|
|
15410
|
+
return record2.kind !== null && record2.kind !== void 0;
|
|
15411
|
+
}
|
|
15412
|
+
function assertValidKindLevel(kind, level) {
|
|
15413
|
+
const hasKind = kind !== null && kind !== void 0;
|
|
15414
|
+
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
15415
|
+
throw new MemoryLevelError(`Unknown memory kind: ${kind}`);
|
|
15416
|
+
}
|
|
15417
|
+
if (level !== void 0 && !MEMORY_LEVELS.includes(level)) {
|
|
15418
|
+
throw new MemoryLevelError(`Unknown memory level: ${level}`);
|
|
15419
|
+
}
|
|
15420
|
+
if (level === "profile" && !hasKind) {
|
|
15421
|
+
throw new MemoryLevelError("Only a memory with a kind can be at level 'profile'");
|
|
15422
|
+
}
|
|
15423
|
+
}
|
|
15424
|
+
function resolveCreateLevel(opts) {
|
|
15425
|
+
if (opts.level !== void 0) return { level: opts.level, scope: scopeForLevel(opts.level) };
|
|
15426
|
+
if (opts.scope !== void 0) return { level: levelFromScope(opts.scope), scope: opts.scope };
|
|
15427
|
+
return { level: "private", scope: "private" };
|
|
15428
|
+
}
|
|
15429
|
+
async function encryptKindValue(ctx, value) {
|
|
15430
|
+
if (typeof value !== "string" || !ctx.walletAddress || !ctx.signMessage) return value;
|
|
15431
|
+
return encryptVaultMemoryContent(
|
|
15432
|
+
value,
|
|
15433
|
+
ctx.walletAddress,
|
|
15434
|
+
ctx.signMessage,
|
|
15435
|
+
ctx.embeddedWalletSigner
|
|
15436
|
+
);
|
|
15437
|
+
}
|
|
15438
|
+
function levelConditions(requested) {
|
|
15439
|
+
if (!requested?.length) return [];
|
|
15440
|
+
const published = ["shared", "public"];
|
|
15441
|
+
const wantsMatching = requested.includes("matching");
|
|
15442
|
+
const wantsPrivate = requested.includes("private");
|
|
15443
|
+
const unresolved = import_watermelondb23.Q.or(import_watermelondb23.Q.where("level", null), import_watermelondb23.Q.where("level", import_watermelondb23.Q.notIn([...MEMORY_LEVELS])));
|
|
15444
|
+
const byLevel = import_watermelondb23.Q.where("level", import_watermelondb23.Q.oneOf([...requested]));
|
|
15445
|
+
if (wantsMatching && wantsPrivate) return [import_watermelondb23.Q.or(byLevel, unresolved)];
|
|
15446
|
+
if (wantsMatching) {
|
|
15447
|
+
return [import_watermelondb23.Q.or(byLevel, import_watermelondb23.Q.and(unresolved, import_watermelondb23.Q.where("scope", import_watermelondb23.Q.oneOf(published))))];
|
|
15448
|
+
}
|
|
15449
|
+
if (wantsPrivate) {
|
|
15450
|
+
return [
|
|
15451
|
+
import_watermelondb23.Q.or(
|
|
15452
|
+
byLevel,
|
|
15453
|
+
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))))
|
|
15454
|
+
)
|
|
15455
|
+
];
|
|
15456
|
+
}
|
|
15457
|
+
return [byLevel];
|
|
15458
|
+
}
|
|
15331
15459
|
function isOwnedByCtxUser(ctx, record2) {
|
|
15332
15460
|
return ctx.userId === void 0 || record2.userId === ctx.userId;
|
|
15333
15461
|
}
|
|
@@ -15371,6 +15499,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
15371
15499
|
uniqueId: memory.id,
|
|
15372
15500
|
content: memory.content,
|
|
15373
15501
|
scope: memory.scope,
|
|
15502
|
+
kind: memory.kind ?? null,
|
|
15503
|
+
kindValue: memory.kindValue ?? null,
|
|
15504
|
+
level: resolveMemoryLevel(memory.level, memory.scope),
|
|
15374
15505
|
folderId: memory.folderId ?? null,
|
|
15375
15506
|
userId: memory.userId ?? null,
|
|
15376
15507
|
embedding: memory.embedding ?? null,
|
|
@@ -15409,9 +15540,13 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
15409
15540
|
}
|
|
15410
15541
|
return raw;
|
|
15411
15542
|
}
|
|
15412
|
-
function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
|
|
15543
|
+
function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue) {
|
|
15544
|
+
const { level, scope } = resolveCreateLevel(opts);
|
|
15413
15545
|
record2._setRaw("content", encryptedContent);
|
|
15414
|
-
record2._setRaw("scope",
|
|
15546
|
+
record2._setRaw("scope", scope);
|
|
15547
|
+
record2._setRaw("level", level);
|
|
15548
|
+
record2._setRaw("kind", opts.kind ?? null);
|
|
15549
|
+
record2._setRaw("kind_value", encryptedKindValue ?? null);
|
|
15415
15550
|
record2._setRaw("folder_id", opts.folderId ?? null);
|
|
15416
15551
|
record2._setRaw("user_id", ctx.userId ?? null);
|
|
15417
15552
|
record2._setRaw("is_deleted", false);
|
|
@@ -15445,6 +15580,8 @@ function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
|
|
|
15445
15580
|
}
|
|
15446
15581
|
}
|
|
15447
15582
|
async function createVaultMemoryOp(ctx, opts) {
|
|
15583
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
15584
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
15448
15585
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15449
15586
|
opts.content,
|
|
15450
15587
|
ctx.walletAddress,
|
|
@@ -15455,13 +15592,15 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
15455
15592
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
15456
15593
|
throw new Error("Memory source is no longer eligible");
|
|
15457
15594
|
return ctx.vaultMemoryCollection.create(
|
|
15458
|
-
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
15595
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
15459
15596
|
);
|
|
15460
15597
|
});
|
|
15461
15598
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
15462
15599
|
}
|
|
15463
15600
|
async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
15464
15601
|
if (!targetId) return { created: null, retired: false };
|
|
15602
|
+
assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
15603
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
15465
15604
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15466
15605
|
opts.content,
|
|
15467
15606
|
ctx.walletAddress,
|
|
@@ -15478,9 +15617,10 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
15478
15617
|
} catch {
|
|
15479
15618
|
return;
|
|
15480
15619
|
}
|
|
15481
|
-
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target))
|
|
15620
|
+
if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
|
|
15621
|
+
return;
|
|
15482
15622
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
15483
|
-
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
|
|
15623
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
15484
15624
|
);
|
|
15485
15625
|
await target.update((r) => {
|
|
15486
15626
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -15544,6 +15684,10 @@ async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
|
|
|
15544
15684
|
}
|
|
15545
15685
|
async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
15546
15686
|
if (optionsArray.length === 0) return [];
|
|
15687
|
+
for (const opts of optionsArray) assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
|
|
15688
|
+
const encryptedKindValues = await Promise.all(
|
|
15689
|
+
optionsArray.map((opts) => encryptKindValue(ctx, opts.kindValue))
|
|
15690
|
+
);
|
|
15547
15691
|
const encryptedContents = await Promise.all(
|
|
15548
15692
|
optionsArray.map(async (opts) => {
|
|
15549
15693
|
if (ctx.walletAddress && ctx.signMessage) {
|
|
@@ -15562,7 +15706,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
15562
15706
|
throw new Error("Memory source is no longer eligible");
|
|
15563
15707
|
const prepared = optionsArray.map(
|
|
15564
15708
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
15565
|
-
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
|
|
15709
|
+
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
15566
15710
|
)
|
|
15567
15711
|
);
|
|
15568
15712
|
await ctx.database.batch(...prepared);
|
|
@@ -15605,6 +15749,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
15605
15749
|
uniqueId: raw.id,
|
|
15606
15750
|
content: raw.content ?? "",
|
|
15607
15751
|
scope: raw.scope ?? "",
|
|
15752
|
+
kind: raw.kind ?? null,
|
|
15753
|
+
kindValue: raw.kind_value ?? null,
|
|
15754
|
+
level: resolveMemoryLevel(raw.level, raw.scope),
|
|
15608
15755
|
folderId: raw.folder_id ?? null,
|
|
15609
15756
|
userId: raw.user_id ?? null,
|
|
15610
15757
|
embedding: raw.embedding ?? null,
|
|
@@ -15648,6 +15795,8 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
15648
15795
|
...baseVaultConditions(ctx, options),
|
|
15649
15796
|
...options?.scopes?.length ? [import_watermelondb23.Q.where("scope", import_watermelondb23.Q.oneOf(options.scopes))] : [],
|
|
15650
15797
|
...visibilityConditions(options?.visibility),
|
|
15798
|
+
...levelConditions(options?.levels),
|
|
15799
|
+
...options?.kinds?.length ? [import_watermelondb23.Q.where("kind", import_watermelondb23.Q.oneOf(options.kinds))] : [],
|
|
15651
15800
|
...options?.folderId !== void 0 ? [import_watermelondb23.Q.where("folder_id", options.folderId)] : [],
|
|
15652
15801
|
...options?.factTypes?.length ? [import_watermelondb23.Q.where("fact_type", import_watermelondb23.Q.oneOf(options.factTypes))] : [],
|
|
15653
15802
|
import_watermelondb23.Q.sortBy(options?.since ? "updated_at" : "created_at", import_watermelondb23.Q.desc),
|
|
@@ -15814,6 +15963,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15814
15963
|
try {
|
|
15815
15964
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
15816
15965
|
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
15966
|
+
if (opts.freeFormOnly && isKinded(probe)) return null;
|
|
15967
|
+
const levelAfter = (current) => {
|
|
15968
|
+
if (opts.level !== void 0) return opts.level;
|
|
15969
|
+
if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
|
|
15970
|
+
return levelForScopeChange(current, opts.scope);
|
|
15971
|
+
};
|
|
15972
|
+
assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
|
|
15973
|
+
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
15817
15974
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15818
15975
|
opts.content,
|
|
15819
15976
|
ctx.walletAddress,
|
|
@@ -15826,10 +15983,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15826
15983
|
await ctx.database.write(async () => {
|
|
15827
15984
|
if (ctx.canWrite && !await ctx.canWrite())
|
|
15828
15985
|
throw new Error("Memory source is no longer eligible");
|
|
15829
|
-
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
15986
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
15830
15987
|
stale = true;
|
|
15831
15988
|
return;
|
|
15832
15989
|
}
|
|
15990
|
+
const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
|
|
15991
|
+
const nextLevel = levelAfter(record2);
|
|
15992
|
+
assertValidKindLevel(nextKind, nextLevel);
|
|
15833
15993
|
let observedSources = [];
|
|
15834
15994
|
let replayedObservation = false;
|
|
15835
15995
|
if (opts.observationSourceIds?.length) {
|
|
@@ -15843,8 +16003,18 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15843
16003
|
}
|
|
15844
16004
|
await record2.update((r) => {
|
|
15845
16005
|
r._setRaw("content", encryptedContent);
|
|
15846
|
-
if (opts.
|
|
16006
|
+
if (opts.level !== void 0) {
|
|
16007
|
+
r._setRaw("level", nextLevel);
|
|
16008
|
+
r._setRaw("scope", scopeForLevel(nextLevel));
|
|
16009
|
+
} else if (opts.scope !== void 0) {
|
|
15847
16010
|
r._setRaw("scope", opts.scope);
|
|
16011
|
+
r._setRaw("level", nextLevel);
|
|
16012
|
+
}
|
|
16013
|
+
if (opts.kind !== void 0) {
|
|
16014
|
+
r._setRaw("kind", opts.kind);
|
|
16015
|
+
}
|
|
16016
|
+
if (encryptedKindValue !== void 0) {
|
|
16017
|
+
r._setRaw("kind_value", encryptedKindValue);
|
|
15848
16018
|
}
|
|
15849
16019
|
if (opts.folderId !== void 0) {
|
|
15850
16020
|
r._setRaw("folder_id", opts.folderId);
|
|
@@ -15903,7 +16073,8 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15903
16073
|
ctx.signMessage,
|
|
15904
16074
|
ctx.embeddedWalletSigner
|
|
15905
16075
|
);
|
|
15906
|
-
} catch {
|
|
16076
|
+
} catch (err) {
|
|
16077
|
+
if (err instanceof MemoryLevelError) throw err;
|
|
15907
16078
|
return null;
|
|
15908
16079
|
}
|
|
15909
16080
|
}
|
|
@@ -16039,6 +16210,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
16039
16210
|
try {
|
|
16040
16211
|
const record2 = await ctx.vaultMemoryCollection.find(id);
|
|
16041
16212
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16213
|
+
if (isKinded(record2)) return false;
|
|
16042
16214
|
let successor;
|
|
16043
16215
|
try {
|
|
16044
16216
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -16339,7 +16511,10 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
16339
16511
|
}
|
|
16340
16512
|
async function getDecayCandidatesRawOp(ctx) {
|
|
16341
16513
|
assertVaultScopeForSweep(ctx);
|
|
16342
|
-
const results = await ctx.vaultMemoryCollection.query(
|
|
16514
|
+
const results = await ctx.vaultMemoryCollection.query(
|
|
16515
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
16516
|
+
import_watermelondb23.Q.where("kind", null)
|
|
16517
|
+
).unsafeFetchRaw();
|
|
16343
16518
|
return results.map((raw) => ({
|
|
16344
16519
|
uniqueId: raw.id,
|
|
16345
16520
|
factType: raw.fact_type ?? null,
|
|
@@ -16600,6 +16775,7 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
16600
16775
|
record2._raw.id = row.memoryId;
|
|
16601
16776
|
record2._setRaw("content", content);
|
|
16602
16777
|
record2._setRaw("scope", "shared");
|
|
16778
|
+
record2._setRaw("level", "matching");
|
|
16603
16779
|
record2._setRaw("folder_id", null);
|
|
16604
16780
|
record2._setRaw("user_id", ctx.userId ?? null);
|
|
16605
16781
|
record2._setRaw("is_deleted", false);
|
|
@@ -17466,6 +17642,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
17466
17642
|
for (const memory of memories) {
|
|
17467
17643
|
updates.push(
|
|
17468
17644
|
memory.prepareUpdate((r) => {
|
|
17645
|
+
r._setRaw("level", levelForScopeChange(r, opts.scope));
|
|
17469
17646
|
r._setRaw("scope", opts.scope);
|
|
17470
17647
|
})
|
|
17471
17648
|
);
|
|
@@ -17487,6 +17664,7 @@ async function deleteVaultFolderOp(ctx, id) {
|
|
|
17487
17664
|
const preparedMemories = memories.map(
|
|
17488
17665
|
(memory) => memory.prepareUpdate((r) => {
|
|
17489
17666
|
r._setRaw("folder_id", null);
|
|
17667
|
+
r._setRaw("level", levelForScopeChange(r, "private"));
|
|
17490
17668
|
r._setRaw("scope", "private");
|
|
17491
17669
|
})
|
|
17492
17670
|
);
|
|
@@ -17523,6 +17701,7 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
17523
17701
|
const prepared = memories.map(
|
|
17524
17702
|
(memory) => memory.prepareUpdate((r) => {
|
|
17525
17703
|
r._setRaw("folder_id", folderId);
|
|
17704
|
+
r._setRaw("level", levelForScopeChange(r, targetScope));
|
|
17526
17705
|
r._setRaw("scope", targetScope);
|
|
17527
17706
|
})
|
|
17528
17707
|
);
|
|
@@ -19855,6 +20034,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
19855
20034
|
includeArchived: true,
|
|
19856
20035
|
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
19857
20036
|
});
|
|
20037
|
+
prepared = withoutKindedRows(prepared);
|
|
19858
20038
|
if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
|
|
19859
20039
|
throw new Error(
|
|
19860
20040
|
"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."
|
|
@@ -19896,6 +20076,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
19896
20076
|
const resurrect = resurrectFields(existing);
|
|
19897
20077
|
const updated = await ctx.persistence.update(targetId, {
|
|
19898
20078
|
content: existing.content,
|
|
20079
|
+
freeFormOnly: true,
|
|
19899
20080
|
proofCountIncrement: 1,
|
|
19900
20081
|
observationSourceIds: options.sourceChunkIds,
|
|
19901
20082
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -20024,6 +20205,17 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
20024
20205
|
...consolidationDecidedCreate && { consolidation: "create" }
|
|
20025
20206
|
};
|
|
20026
20207
|
}
|
|
20208
|
+
function withoutKindedRows(prepared) {
|
|
20209
|
+
const kinded = new Set(
|
|
20210
|
+
prepared.memories.filter((m) => m.kind !== null && m.kind !== void 0).map((m) => m.uniqueId)
|
|
20211
|
+
);
|
|
20212
|
+
if (kinded.size === 0) return prepared;
|
|
20213
|
+
return {
|
|
20214
|
+
...prepared,
|
|
20215
|
+
memories: prepared.memories.filter((m) => !kinded.has(m.uniqueId)),
|
|
20216
|
+
embeddedItems: prepared.embeddedItems.filter((item) => !kinded.has(item.id))
|
|
20217
|
+
};
|
|
20218
|
+
}
|
|
20027
20219
|
function unionStrings(a, b) {
|
|
20028
20220
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
20029
20221
|
}
|
|
@@ -20123,6 +20315,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20123
20315
|
const resurrect = resurrectFields(existing);
|
|
20124
20316
|
const updated = await ctx.persistence.update(decision.targetId, {
|
|
20125
20317
|
content: existing.content,
|
|
20318
|
+
freeFormOnly: true,
|
|
20126
20319
|
proofCountIncrement: 1,
|
|
20127
20320
|
observationSourceIds: options.sourceChunkIds,
|
|
20128
20321
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -20168,6 +20361,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20168
20361
|
const resurrect = resurrectFields(existing);
|
|
20169
20362
|
const updated = await ctx.persistence.update(decision.targetId, {
|
|
20170
20363
|
content: decision.content,
|
|
20364
|
+
freeFormOnly: true,
|
|
20171
20365
|
proofCountIncrement: 1,
|
|
20172
20366
|
observationSourceIds: options.sourceChunkIds,
|
|
20173
20367
|
sourceChunkIds: mergedSourceIds,
|
|
@@ -20211,7 +20405,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
20211
20405
|
}
|
|
20212
20406
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
20213
20407
|
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
20214
|
-
if (stillExists) {
|
|
20408
|
+
if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
|
|
20215
20409
|
throw new Error(`retain: merge into memory ${targetId} failed to persist`);
|
|
20216
20410
|
}
|
|
20217
20411
|
}
|
|
@@ -22874,6 +23068,65 @@ function createLocalMemoryStore(options) {
|
|
|
22874
23068
|
};
|
|
22875
23069
|
}
|
|
22876
23070
|
|
|
23071
|
+
// src/lib/memory/store/memoryKeys.ts
|
|
23072
|
+
var KEY_ID_DOMAIN = "anuma-private-memory-key-id-v1";
|
|
23073
|
+
var MemoryKeyError = class extends Error {
|
|
23074
|
+
constructor(message) {
|
|
23075
|
+
super(message);
|
|
23076
|
+
this.name = "MemoryKeyError";
|
|
23077
|
+
}
|
|
23078
|
+
};
|
|
23079
|
+
async function importAesKey(hex) {
|
|
23080
|
+
return crypto.subtle.importKey(
|
|
23081
|
+
"raw",
|
|
23082
|
+
hexToBytes(hex).buffer,
|
|
23083
|
+
{ name: "AES-GCM" },
|
|
23084
|
+
false,
|
|
23085
|
+
["encrypt", "decrypt"]
|
|
23086
|
+
);
|
|
23087
|
+
}
|
|
23088
|
+
async function deriveMemoryKeyRing(signatureHex) {
|
|
23089
|
+
const v3Hex = await deriveKeyFromSignatureV3(signatureHex);
|
|
23090
|
+
const digest = await crypto.subtle.digest(
|
|
23091
|
+
"SHA-256",
|
|
23092
|
+
new TextEncoder().encode(`${KEY_ID_DOMAIN}:${v3Hex}`)
|
|
23093
|
+
);
|
|
23094
|
+
const keyId = "v3:" + Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
23095
|
+
return {
|
|
23096
|
+
keyId,
|
|
23097
|
+
v3: await importAesKey(v3Hex),
|
|
23098
|
+
v2: await importAesKey(await deriveKeyFromSignature(signatureHex))
|
|
23099
|
+
};
|
|
23100
|
+
}
|
|
23101
|
+
async function decryptWith(value, rings) {
|
|
23102
|
+
const version = value.startsWith("enc:v3:") ? "v3" : "v2";
|
|
23103
|
+
for (const ring of rings) {
|
|
23104
|
+
try {
|
|
23105
|
+
return await decryptDataWithKey(value.slice(`enc:${version}:`.length), ring[version]);
|
|
23106
|
+
} catch {
|
|
23107
|
+
continue;
|
|
23108
|
+
}
|
|
23109
|
+
}
|
|
23110
|
+
throw new MemoryKeyError(`No supplied key decrypts this enc:${version} field`);
|
|
23111
|
+
}
|
|
23112
|
+
function memoryCipher(canonical) {
|
|
23113
|
+
return {
|
|
23114
|
+
encrypt: async (plaintext) => `enc:v3:${await encryptDataWithKey(plaintext, canonical.v3)}`,
|
|
23115
|
+
decrypt: async (ciphertext) => {
|
|
23116
|
+
if (!ciphertext.startsWith("enc:v3:") || !isEncrypted(ciphertext))
|
|
23117
|
+
throw new MemoryKeyError("Remote memory content must be enc:v3 ciphertext");
|
|
23118
|
+
return decryptWith(ciphertext, [canonical]);
|
|
23119
|
+
}
|
|
23120
|
+
};
|
|
23121
|
+
}
|
|
23122
|
+
async function reencryptMemoryField(value, canonical, fallbacks = []) {
|
|
23123
|
+
const { encrypt } = memoryCipher(canonical);
|
|
23124
|
+
if (!value.startsWith("enc:")) return encrypt(value);
|
|
23125
|
+
if (!isEncrypted(value))
|
|
23126
|
+
throw new MemoryKeyError("Field has an encryption prefix but an invalid payload");
|
|
23127
|
+
return encrypt(await decryptWith(value, [canonical, ...fallbacks]));
|
|
23128
|
+
}
|
|
23129
|
+
|
|
22877
23130
|
// src/lib/memory/store/remotePersistence.ts
|
|
22878
23131
|
var RemoteMemoryError = class extends Error {
|
|
22879
23132
|
constructor(message, status, code) {
|
|
@@ -22926,6 +23179,30 @@ var candidateListLimits = [
|
|
|
22926
23179
|
["memory_ids", 1e3],
|
|
22927
23180
|
["force_ids", 100]
|
|
22928
23181
|
];
|
|
23182
|
+
var queryListLimits = [
|
|
23183
|
+
["scopes", 20],
|
|
23184
|
+
["fact_types", 20],
|
|
23185
|
+
["visibility", 20],
|
|
23186
|
+
["memory_ids", 1e3],
|
|
23187
|
+
["topics", 100]
|
|
23188
|
+
];
|
|
23189
|
+
var queryFields = [
|
|
23190
|
+
"include_deleted",
|
|
23191
|
+
"include_archived",
|
|
23192
|
+
"include_quarantined",
|
|
23193
|
+
"include_superseded",
|
|
23194
|
+
"archived_only",
|
|
23195
|
+
"scopes",
|
|
23196
|
+
"fact_types",
|
|
23197
|
+
"visibility",
|
|
23198
|
+
"memory_ids",
|
|
23199
|
+
"topics",
|
|
23200
|
+
"updated_after",
|
|
23201
|
+
"order",
|
|
23202
|
+
"cursor",
|
|
23203
|
+
"limit",
|
|
23204
|
+
"include_embeddings"
|
|
23205
|
+
];
|
|
22929
23206
|
function record(value) {
|
|
22930
23207
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22931
23208
|
}
|
|
@@ -23260,6 +23537,35 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
23260
23537
|
throw new Error("Invalid nearby batch response");
|
|
23261
23538
|
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
23262
23539
|
},
|
|
23540
|
+
query: async (queryOptions = {}) => {
|
|
23541
|
+
const { signal, ...query } = queryOptions;
|
|
23542
|
+
if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200))
|
|
23543
|
+
throw new Error("Page limit must be 1\u2013200");
|
|
23544
|
+
for (const [key, max] of queryListLimits) {
|
|
23545
|
+
const values = query[key];
|
|
23546
|
+
if (values && values.length > max)
|
|
23547
|
+
throw new Error(`Query ${key} accepts at most ${max} entries (got ${values.length})`);
|
|
23548
|
+
}
|
|
23549
|
+
const page = await request(
|
|
23550
|
+
"/memories/query",
|
|
23551
|
+
{
|
|
23552
|
+
method: "POST",
|
|
23553
|
+
body: JSON.stringify(
|
|
23554
|
+
Object.fromEntries(
|
|
23555
|
+
queryFields.filter((key) => query[key] !== void 0).map((key) => [key, query[key]])
|
|
23556
|
+
)
|
|
23557
|
+
)
|
|
23558
|
+
},
|
|
23559
|
+
signal
|
|
23560
|
+
);
|
|
23561
|
+
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")
|
|
23562
|
+
throw new Error("Invalid nearby private-memory page");
|
|
23563
|
+
return {
|
|
23564
|
+
...await decodeAll(page.items),
|
|
23565
|
+
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor },
|
|
23566
|
+
...page.changes_cursor !== void 0 && { changes_cursor: page.changes_cursor }
|
|
23567
|
+
};
|
|
23568
|
+
},
|
|
23263
23569
|
candidateSet,
|
|
23264
23570
|
candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
|
|
23265
23571
|
};
|
|
@@ -23285,6 +23591,9 @@ function sourceIds(value) {
|
|
|
23285
23591
|
return [];
|
|
23286
23592
|
}
|
|
23287
23593
|
}
|
|
23594
|
+
function isMemoryLevel(value) {
|
|
23595
|
+
return MEMORY_LEVELS.includes(value);
|
|
23596
|
+
}
|
|
23288
23597
|
function stored(row) {
|
|
23289
23598
|
return {
|
|
23290
23599
|
uniqueId: row.memory_id,
|
|
@@ -23292,6 +23601,9 @@ function stored(row) {
|
|
|
23292
23601
|
scope: row.scope,
|
|
23293
23602
|
folderId: row.folder_id ?? null,
|
|
23294
23603
|
userId: null,
|
|
23604
|
+
kind: row.kind ?? null,
|
|
23605
|
+
kindValue: row.kind_value ?? null,
|
|
23606
|
+
...isMemoryLevel(row.level) && { level: row.level },
|
|
23295
23607
|
embedding: row.embedding ? JSON.stringify(row.embedding) : null,
|
|
23296
23608
|
embeddingModel: row.embedding_model ?? null,
|
|
23297
23609
|
sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
|
|
@@ -23513,7 +23825,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23513
23825
|
create: (input) => write(createRow(input), 0),
|
|
23514
23826
|
update: async (id, patch) => {
|
|
23515
23827
|
const existing = await get(id);
|
|
23516
|
-
if (!existing
|
|
23828
|
+
if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
|
|
23829
|
+
return null;
|
|
23517
23830
|
const snapshot = snapshots.get(id);
|
|
23518
23831
|
const memory = {
|
|
23519
23832
|
...snapshot.memory,
|
|
@@ -23642,6 +23955,490 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23642
23955
|
};
|
|
23643
23956
|
}
|
|
23644
23957
|
|
|
23958
|
+
// src/lib/memory/store/remoteStore.ts
|
|
23959
|
+
var import_uuid6 = require("uuid");
|
|
23960
|
+
init_logger();
|
|
23961
|
+
function relevant(change, options) {
|
|
23962
|
+
return options.includeDeleted ? change === "membership" : change !== "embedding" || !!options.embeddings;
|
|
23963
|
+
}
|
|
23964
|
+
function safely(onChange) {
|
|
23965
|
+
try {
|
|
23966
|
+
onChange();
|
|
23967
|
+
} catch (error) {
|
|
23968
|
+
getLogger().warn("[memory/remote-store] Subscriber threw:", error);
|
|
23969
|
+
}
|
|
23970
|
+
}
|
|
23971
|
+
var MAX_BATCH = 50;
|
|
23972
|
+
var MAX_QUERY_IDS = 1e3;
|
|
23973
|
+
var MAX_QUERY_TOPICS = 100;
|
|
23974
|
+
var MAX_QUERY_FILTER = 20;
|
|
23975
|
+
var RemoteMemoryPartialCreateError = class extends Error {
|
|
23976
|
+
constructor(created, cause) {
|
|
23977
|
+
super(`createMany stored ${created.length} memories before a batch failed`);
|
|
23978
|
+
this.created = created;
|
|
23979
|
+
this.cause = cause;
|
|
23980
|
+
this.name = "RemoteMemoryPartialCreateError";
|
|
23981
|
+
}
|
|
23982
|
+
};
|
|
23983
|
+
function warnFailed(failed) {
|
|
23984
|
+
if (failed.length)
|
|
23985
|
+
getLogger().warn(
|
|
23986
|
+
`[memory/remote-store] Skipping ${failed.length} undecryptable row(s)`,
|
|
23987
|
+
failed.map((failure) => failure.memory_id)
|
|
23988
|
+
);
|
|
23989
|
+
}
|
|
23990
|
+
function bounded(filters, key) {
|
|
23991
|
+
const values = filters[key];
|
|
23992
|
+
if (!values || values.length <= MAX_QUERY_FILTER) return [filters];
|
|
23993
|
+
return chunks(values, MAX_QUERY_FILTER).map((chunk) => ({ ...filters, [key]: chunk }));
|
|
23994
|
+
}
|
|
23995
|
+
function chunks(values, size) {
|
|
23996
|
+
const out = [];
|
|
23997
|
+
for (let i = 0; i < values.length; i += size) out.push(values.slice(i, i + size));
|
|
23998
|
+
return out;
|
|
23999
|
+
}
|
|
24000
|
+
function stateFilters(options) {
|
|
24001
|
+
return {
|
|
24002
|
+
include_deleted: options.includeDeleted,
|
|
24003
|
+
include_archived: options.includeArchived,
|
|
24004
|
+
include_quarantined: options.includeQuarantined,
|
|
24005
|
+
include_superseded: options.includeSuperseded
|
|
24006
|
+
};
|
|
24007
|
+
}
|
|
24008
|
+
function hidden(memory, options) {
|
|
24009
|
+
if (memory.trust_tier === "quarantined") return true;
|
|
24010
|
+
if (options.includeDeleted) return false;
|
|
24011
|
+
return !!memory.is_deleted || memory.archived_at !== void 0 && memory.archived_at !== null || !!memory.superseded_by;
|
|
24012
|
+
}
|
|
24013
|
+
function subscriptionKey({ memory, version }, options) {
|
|
24014
|
+
if (hidden(memory, options)) return void 0;
|
|
24015
|
+
if (options.includeDeleted) return String(!!memory.is_deleted);
|
|
24016
|
+
return JSON.stringify([
|
|
24017
|
+
options.embeddings ? version : null,
|
|
24018
|
+
memory.content,
|
|
24019
|
+
memory.scope,
|
|
24020
|
+
memory.updated_at,
|
|
24021
|
+
memory.fact_type,
|
|
24022
|
+
memory.event_time_start,
|
|
24023
|
+
memory.event_time_end,
|
|
24024
|
+
memory.event_time_kind,
|
|
24025
|
+
memory.trust_tier,
|
|
24026
|
+
memory.visibility,
|
|
24027
|
+
memory.published_at,
|
|
24028
|
+
memory.geohash,
|
|
24029
|
+
memory.topics,
|
|
24030
|
+
memory.topics_user_managed,
|
|
24031
|
+
memory.media,
|
|
24032
|
+
memory.source
|
|
24033
|
+
]);
|
|
24034
|
+
}
|
|
24035
|
+
function topicInputs(topics, source) {
|
|
24036
|
+
return topics.flatMap((topic) => {
|
|
24037
|
+
const name = (typeof topic === "string" ? topic : topic.name).trim();
|
|
24038
|
+
const kind = typeof topic === "string" ? void 0 : topic.kind;
|
|
24039
|
+
return name ? [{ name, ...kind && { kind }, source }] : [];
|
|
24040
|
+
});
|
|
24041
|
+
}
|
|
24042
|
+
function mergeTopics(existing, added) {
|
|
24043
|
+
const byName = /* @__PURE__ */ new Map();
|
|
24044
|
+
for (const topic of [...existing, ...added]) {
|
|
24045
|
+
const key = normalizeEntityName(topic.name);
|
|
24046
|
+
if (!byName.has(key)) byName.set(key, topic);
|
|
24047
|
+
}
|
|
24048
|
+
return [...byName.values()];
|
|
24049
|
+
}
|
|
24050
|
+
function canonicalTopics(row) {
|
|
24051
|
+
return new Set((parseTopics(row.topics) ?? []).map((topic) => normalizeEntityName(topic.name)));
|
|
24052
|
+
}
|
|
24053
|
+
function createRemoteMemoryStore(options) {
|
|
24054
|
+
const { persistence, embeddingOptions } = options;
|
|
24055
|
+
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
24056
|
+
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
24057
|
+
const pipeline = createRemoteMemoryPipeline(options);
|
|
24058
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
24059
|
+
const seen = /* @__PURE__ */ new Map();
|
|
24060
|
+
let timer;
|
|
24061
|
+
const notify = (change, records = []) => {
|
|
24062
|
+
if (timer) for (const record2 of records) seen.set(record2.memory.memory_id, record2);
|
|
24063
|
+
for (const subscriber of [...subscribers])
|
|
24064
|
+
if (relevant(change, subscriber.options)) safely(subscriber.onChange);
|
|
24065
|
+
};
|
|
24066
|
+
const enumerate = async (filters, max = Infinity) => {
|
|
24067
|
+
const records = [];
|
|
24068
|
+
let cursor2;
|
|
24069
|
+
do {
|
|
24070
|
+
const page = await persistence.query({
|
|
24071
|
+
...filters,
|
|
24072
|
+
limit: Math.min(200, Math.max(1, max - records.length)),
|
|
24073
|
+
...cursor2 && { cursor: cursor2 }
|
|
24074
|
+
});
|
|
24075
|
+
warnFailed(page.failed);
|
|
24076
|
+
records.push(...page.items);
|
|
24077
|
+
cursor2 = page.next_cursor;
|
|
24078
|
+
} while (cursor2 && records.length < max);
|
|
24079
|
+
return records.slice(0, max);
|
|
24080
|
+
};
|
|
24081
|
+
const enumerateIds = async (ids, filters) => (await Promise.all(
|
|
24082
|
+
chunks([...new Set(ids)], MAX_QUERY_IDS).map(
|
|
24083
|
+
(memory_ids) => enumerate({ ...filters, memory_ids })
|
|
24084
|
+
)
|
|
24085
|
+
)).flat();
|
|
24086
|
+
const queues = /* @__PURE__ */ new Map();
|
|
24087
|
+
const serialized = (id, task) => {
|
|
24088
|
+
const run = (queues.get(id) ?? Promise.resolve()).then(task, task);
|
|
24089
|
+
const settled = run.catch(() => void 0);
|
|
24090
|
+
queues.set(id, settled);
|
|
24091
|
+
void settled.then(() => {
|
|
24092
|
+
if (queues.get(id) === settled) queues.delete(id);
|
|
24093
|
+
});
|
|
24094
|
+
return run;
|
|
24095
|
+
};
|
|
24096
|
+
const live = async (id) => {
|
|
24097
|
+
const record2 = await persistence.get(id);
|
|
24098
|
+
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
24099
|
+
};
|
|
24100
|
+
const mutate = async (id, change, edit) => serialized(id, async () => {
|
|
24101
|
+
const record2 = await live(id);
|
|
24102
|
+
if (!record2) return null;
|
|
24103
|
+
const next = edit(structuredClone(record2.memory));
|
|
24104
|
+
if (!next) return null;
|
|
24105
|
+
const saved = await persistence.put(next, record2);
|
|
24106
|
+
notify(change, [saved]);
|
|
24107
|
+
return saved;
|
|
24108
|
+
});
|
|
24109
|
+
const embedInBackground = ({ memory: { memory_id: id, content } }) => {
|
|
24110
|
+
generateEmbedding(content, embeddingOptions).then(
|
|
24111
|
+
(vector) => serialized(id, async () => {
|
|
24112
|
+
const current = await live(id);
|
|
24113
|
+
if (!current || current.memory.content !== content || current.memory.embedding?.length)
|
|
24114
|
+
return;
|
|
24115
|
+
const saved = await persistence.put(
|
|
24116
|
+
{ ...current.memory, embedding: storedVector(vector), embedding_model: model },
|
|
24117
|
+
current
|
|
24118
|
+
);
|
|
24119
|
+
notify("embedding", [saved]);
|
|
24120
|
+
})
|
|
24121
|
+
).catch((error) => {
|
|
24122
|
+
getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
|
|
24123
|
+
});
|
|
24124
|
+
};
|
|
24125
|
+
const newRow = (input) => {
|
|
24126
|
+
const now = Date.now();
|
|
24127
|
+
const scope = input.scope ?? "private";
|
|
24128
|
+
return {
|
|
24129
|
+
memory_id: (0, import_uuid6.v7)(),
|
|
24130
|
+
content: input.content,
|
|
24131
|
+
scope,
|
|
24132
|
+
level: levelFromScope(scope),
|
|
24133
|
+
created_at: now,
|
|
24134
|
+
updated_at: now,
|
|
24135
|
+
is_deleted: false,
|
|
24136
|
+
...input.embedding !== void 0 && {
|
|
24137
|
+
embedding: storedVector(JSON.parse(input.embedding)),
|
|
24138
|
+
embedding_model: input.embeddingModel ?? model
|
|
24139
|
+
},
|
|
24140
|
+
proof_count: 1,
|
|
24141
|
+
source: "manual",
|
|
24142
|
+
...input.eventTime && {
|
|
24143
|
+
event_time_start: input.eventTime.start ?? void 0,
|
|
24144
|
+
event_time_end: input.eventTime.end ?? void 0,
|
|
24145
|
+
event_time_kind: input.eventTime.kind ?? void 0
|
|
24146
|
+
},
|
|
24147
|
+
fact_type: input.factType,
|
|
24148
|
+
geohash: input.geohash,
|
|
24149
|
+
visibility: "private",
|
|
24150
|
+
twin_opt_in: false
|
|
24151
|
+
};
|
|
24152
|
+
};
|
|
24153
|
+
const created = (records, inputs) => {
|
|
24154
|
+
records.forEach((record2, i) => {
|
|
24155
|
+
if (inputs[i].embedding === void 0) embedInBackground(record2);
|
|
24156
|
+
});
|
|
24157
|
+
notify("membership", records);
|
|
24158
|
+
return records.map((record2) => stored(record2.memory));
|
|
24159
|
+
};
|
|
24160
|
+
const asStored = (record2) => record2 ? stored(record2.memory) : null;
|
|
24161
|
+
const everyState = {
|
|
24162
|
+
include_deleted: true,
|
|
24163
|
+
include_archived: true,
|
|
24164
|
+
include_quarantined: true,
|
|
24165
|
+
include_superseded: true
|
|
24166
|
+
};
|
|
24167
|
+
const changesSince = async (cursor2, pending2) => {
|
|
24168
|
+
const records = [];
|
|
24169
|
+
const failed = /* @__PURE__ */ new Set();
|
|
24170
|
+
const collect = (page) => {
|
|
24171
|
+
warnFailed(page.failed);
|
|
24172
|
+
records.push(...page.items);
|
|
24173
|
+
for (const failure of page.failed) failed.add(failure.memory_id);
|
|
24174
|
+
};
|
|
24175
|
+
let resume = cursor2;
|
|
24176
|
+
let next;
|
|
24177
|
+
do {
|
|
24178
|
+
const page = await persistence.query({
|
|
24179
|
+
...everyState,
|
|
24180
|
+
order: "changed",
|
|
24181
|
+
limit: 200,
|
|
24182
|
+
...(next ?? resume) && { cursor: next ?? resume }
|
|
24183
|
+
});
|
|
24184
|
+
collect(page);
|
|
24185
|
+
resume = page.changes_cursor ?? resume;
|
|
24186
|
+
next = page.next_cursor;
|
|
24187
|
+
} while (next);
|
|
24188
|
+
for (const memory_ids of chunks([...pending2], MAX_QUERY_IDS)) {
|
|
24189
|
+
let retry;
|
|
24190
|
+
do {
|
|
24191
|
+
const page = await persistence.query({
|
|
24192
|
+
...everyState,
|
|
24193
|
+
memory_ids,
|
|
24194
|
+
limit: 200,
|
|
24195
|
+
...retry && { cursor: retry }
|
|
24196
|
+
});
|
|
24197
|
+
collect(page);
|
|
24198
|
+
retry = page.next_cursor;
|
|
24199
|
+
} while (retry);
|
|
24200
|
+
}
|
|
24201
|
+
return { records, resume, failed };
|
|
24202
|
+
};
|
|
24203
|
+
let generation = 0;
|
|
24204
|
+
let ready = false;
|
|
24205
|
+
let cursor;
|
|
24206
|
+
let pending = /* @__PURE__ */ new Set();
|
|
24207
|
+
let polling = false;
|
|
24208
|
+
const poll = () => {
|
|
24209
|
+
if (polling) return;
|
|
24210
|
+
polling = true;
|
|
24211
|
+
const current = generation;
|
|
24212
|
+
changesSince(cursor, pending).then(({ records, resume, failed }) => {
|
|
24213
|
+
if (current !== generation) return;
|
|
24214
|
+
const changed = /* @__PURE__ */ new Set();
|
|
24215
|
+
for (const record2 of records) {
|
|
24216
|
+
const id = record2.memory.memory_id;
|
|
24217
|
+
const previous = seen.get(id);
|
|
24218
|
+
seen.set(id, record2);
|
|
24219
|
+
if (!ready) continue;
|
|
24220
|
+
for (const subscriber of subscribers) {
|
|
24221
|
+
const before = previous && subscriptionKey(previous, subscriber.options);
|
|
24222
|
+
if (before !== subscriptionKey(record2, subscriber.options)) changed.add(subscriber);
|
|
24223
|
+
}
|
|
24224
|
+
}
|
|
24225
|
+
ready = true;
|
|
24226
|
+
cursor = resume;
|
|
24227
|
+
pending = failed;
|
|
24228
|
+
for (const subscriber of changed)
|
|
24229
|
+
if (subscribers.has(subscriber)) safely(subscriber.onChange);
|
|
24230
|
+
}).catch((error) => {
|
|
24231
|
+
getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
|
|
24232
|
+
}).finally(() => {
|
|
24233
|
+
polling = false;
|
|
24234
|
+
});
|
|
24235
|
+
};
|
|
24236
|
+
return {
|
|
24237
|
+
list: async (listOptions = {}) => {
|
|
24238
|
+
const order = listOptions.since ? "updated" : "created";
|
|
24239
|
+
const filters = {
|
|
24240
|
+
...stateFilters(listOptions),
|
|
24241
|
+
include_embeddings: true,
|
|
24242
|
+
order,
|
|
24243
|
+
...listOptions.scopes?.length && { scopes: listOptions.scopes },
|
|
24244
|
+
...listOptions.factTypes?.length && { fact_types: listOptions.factTypes },
|
|
24245
|
+
...listOptions.visibility?.length && { visibility: listOptions.visibility },
|
|
24246
|
+
...listOptions.since && { updated_after: listOptions.since.getTime() }
|
|
24247
|
+
};
|
|
24248
|
+
const max = listOptions.limit && listOptions.limit > 0 ? listOptions.limit : Infinity;
|
|
24249
|
+
const variants = bounded(filters, "scopes").flatMap((f) => bounded(f, "fact_types"));
|
|
24250
|
+
if (!listOptions.memoryIds && variants.length === 1)
|
|
24251
|
+
return (await enumerate(filters, max)).map((r) => stored(r.memory));
|
|
24252
|
+
const fetched = await Promise.all(
|
|
24253
|
+
variants.map(
|
|
24254
|
+
(variant) => listOptions.memoryIds ? enumerateIds(listOptions.memoryIds, variant) : enumerate(variant, max)
|
|
24255
|
+
)
|
|
24256
|
+
);
|
|
24257
|
+
const rows = [...new Map(fetched.flat().map((r) => [r.memory.memory_id, r])).values()].map((record2) => stored(record2.memory)).sort(
|
|
24258
|
+
(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)
|
|
24259
|
+
);
|
|
24260
|
+
return rows.slice(0, max);
|
|
24261
|
+
},
|
|
24262
|
+
get: async (id) => asStored(await live(id)),
|
|
24263
|
+
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
24264
|
+
(record2) => stored(record2.memory)
|
|
24265
|
+
),
|
|
24266
|
+
memoriesByTopics: async (names) => {
|
|
24267
|
+
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
24268
|
+
const out = /* @__PURE__ */ new Map();
|
|
24269
|
+
const pages = await Promise.all(
|
|
24270
|
+
chunks([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
24271
|
+
);
|
|
24272
|
+
for (const { memory } of pages.flat()) {
|
|
24273
|
+
const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
|
|
24274
|
+
if (matched.length) out.set(memory.memory_id, new Set(matched));
|
|
24275
|
+
}
|
|
24276
|
+
return out;
|
|
24277
|
+
},
|
|
24278
|
+
topicsByMemories: async (memoryIds) => {
|
|
24279
|
+
const out = /* @__PURE__ */ new Map();
|
|
24280
|
+
for (const { memory } of await enumerateIds(memoryIds, {
|
|
24281
|
+
include_archived: true,
|
|
24282
|
+
include_superseded: true,
|
|
24283
|
+
include_quarantined: true
|
|
24284
|
+
})) {
|
|
24285
|
+
const topics = canonicalTopics(memory);
|
|
24286
|
+
if (topics.size) out.set(memory.memory_id, topics);
|
|
24287
|
+
}
|
|
24288
|
+
return out;
|
|
24289
|
+
},
|
|
24290
|
+
create: async (input) => {
|
|
24291
|
+
const record2 = await persistence.put(newRow(input), 0);
|
|
24292
|
+
return created([record2], [input])[0];
|
|
24293
|
+
},
|
|
24294
|
+
createMany: async (inputs) => {
|
|
24295
|
+
const out = [];
|
|
24296
|
+
for (const batch of chunks(inputs, MAX_BATCH)) {
|
|
24297
|
+
let records;
|
|
24298
|
+
try {
|
|
24299
|
+
records = await persistence.putMany(
|
|
24300
|
+
batch.map((input) => ({ memory: newRow(input), expectedVersion: 0 }))
|
|
24301
|
+
);
|
|
24302
|
+
} catch (error) {
|
|
24303
|
+
if (out.length === 0) throw error;
|
|
24304
|
+
throw new RemoteMemoryPartialCreateError(out, error);
|
|
24305
|
+
}
|
|
24306
|
+
out.push(...created(records, batch));
|
|
24307
|
+
}
|
|
24308
|
+
return out;
|
|
24309
|
+
},
|
|
24310
|
+
update: async (id, patch) => {
|
|
24311
|
+
const saved = await mutate(id, "edit", (memory) => {
|
|
24312
|
+
if (memory.superseded_by) return null;
|
|
24313
|
+
memory.content = patch.content;
|
|
24314
|
+
memory.updated_at = Date.now();
|
|
24315
|
+
if (patch.scope !== void 0) {
|
|
24316
|
+
memory.level = levelForScopeChange(
|
|
24317
|
+
{ level: memory.level, scope: memory.scope },
|
|
24318
|
+
patch.scope
|
|
24319
|
+
);
|
|
24320
|
+
memory.scope = patch.scope;
|
|
24321
|
+
}
|
|
24322
|
+
if (patch.factType !== void 0) memory.fact_type = patch.factType ?? void 0;
|
|
24323
|
+
if (patch.eventTime !== void 0) {
|
|
24324
|
+
memory.event_time_start = patch.eventTime?.start ?? void 0;
|
|
24325
|
+
memory.event_time_end = patch.eventTime?.end ?? void 0;
|
|
24326
|
+
memory.event_time_kind = patch.eventTime?.kind ?? void 0;
|
|
24327
|
+
}
|
|
24328
|
+
if (patch.embedding === void 0 || patch.embedding === null) {
|
|
24329
|
+
memory.embedding = [];
|
|
24330
|
+
delete memory.embedding_model;
|
|
24331
|
+
} else {
|
|
24332
|
+
memory.embedding = storedVector(JSON.parse(patch.embedding));
|
|
24333
|
+
memory.embedding_model = patch.embeddingModel ?? model;
|
|
24334
|
+
}
|
|
24335
|
+
return memory;
|
|
24336
|
+
});
|
|
24337
|
+
if (saved && patch.embedding === void 0) embedInBackground(saved);
|
|
24338
|
+
return asStored(saved);
|
|
24339
|
+
},
|
|
24340
|
+
delete: async (id) => !!await mutate(id, "membership", (memory) => ({ ...memory, is_deleted: true })),
|
|
24341
|
+
supersede: async (id, supersededById) => {
|
|
24342
|
+
if (id === supersededById) return false;
|
|
24343
|
+
const [first, second] = [id, supersededById].sort();
|
|
24344
|
+
return serialized(
|
|
24345
|
+
first,
|
|
24346
|
+
() => serialized(second, async () => {
|
|
24347
|
+
const [old, next] = await Promise.all([live(id), live(supersededById)]);
|
|
24348
|
+
if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
|
|
24349
|
+
if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
|
|
24350
|
+
const saved = await persistence.putMany([
|
|
24351
|
+
{
|
|
24352
|
+
memory: { ...old.memory, superseded_by: supersededById, superseded_at: Date.now() },
|
|
24353
|
+
expectedVersion: old
|
|
24354
|
+
},
|
|
24355
|
+
{ memory: next.memory, expectedVersion: next }
|
|
24356
|
+
]);
|
|
24357
|
+
notify("membership", saved);
|
|
24358
|
+
return true;
|
|
24359
|
+
})
|
|
24360
|
+
);
|
|
24361
|
+
},
|
|
24362
|
+
archive: async (id) => !!await mutate(
|
|
24363
|
+
id,
|
|
24364
|
+
"edit",
|
|
24365
|
+
(memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
|
|
24366
|
+
),
|
|
24367
|
+
restore: (id) => serialized(id, async () => {
|
|
24368
|
+
const record2 = await live(id);
|
|
24369
|
+
if (!record2) return false;
|
|
24370
|
+
if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
|
|
24371
|
+
return true;
|
|
24372
|
+
const { archived_at: _archivedAt, ...memory } = record2.memory;
|
|
24373
|
+
notify("edit", [await persistence.put(memory, record2)]);
|
|
24374
|
+
return true;
|
|
24375
|
+
}),
|
|
24376
|
+
setTopics: async (memoryId, topics) => asStored(
|
|
24377
|
+
await mutate(memoryId, "edit", (memory) => ({
|
|
24378
|
+
...memory,
|
|
24379
|
+
topics: serializeTopics(mergeTopics([], topicInputs(topics, "user"))),
|
|
24380
|
+
topics_user_managed: true,
|
|
24381
|
+
topics_updated_at: Date.now()
|
|
24382
|
+
}))
|
|
24383
|
+
),
|
|
24384
|
+
addTopics: async (memoryId, topics) => {
|
|
24385
|
+
const added = topicInputs(topics, "auto");
|
|
24386
|
+
const saved = await mutate(memoryId, "edit", (memory) => ({
|
|
24387
|
+
...memory,
|
|
24388
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
24389
|
+
topics_updated_at: Date.now()
|
|
24390
|
+
}));
|
|
24391
|
+
if (!saved) return [];
|
|
24392
|
+
const now = /* @__PURE__ */ new Date();
|
|
24393
|
+
return mergeTopics([], added).map(
|
|
24394
|
+
(topic) => ({
|
|
24395
|
+
uniqueId: normalizeEntityName(topic.name),
|
|
24396
|
+
canonicalName: normalizeEntityName(topic.name),
|
|
24397
|
+
kind: topic.kind ?? null,
|
|
24398
|
+
createdAt: now,
|
|
24399
|
+
updatedAt: now
|
|
24400
|
+
})
|
|
24401
|
+
);
|
|
24402
|
+
},
|
|
24403
|
+
setVisibility: async (id, visibility, visibilityOptions) => asStored(
|
|
24404
|
+
await mutate(id, "edit", (memory) => {
|
|
24405
|
+
memory.visibility = visibility;
|
|
24406
|
+
if (visibility === "private") delete memory.published_at;
|
|
24407
|
+
else memory.published_at ?? (memory.published_at = Date.now());
|
|
24408
|
+
if (visibilityOptions?.twinOptIn !== void 0)
|
|
24409
|
+
memory.twin_opt_in = visibilityOptions.twinOptIn;
|
|
24410
|
+
return memory;
|
|
24411
|
+
})
|
|
24412
|
+
),
|
|
24413
|
+
recall: (query, recallOptions) => pipeline.recall(query, recallOptions),
|
|
24414
|
+
retain: async (content, retainOptions) => {
|
|
24415
|
+
const result = await pipeline.retain(content, retainOptions);
|
|
24416
|
+
if (result.action === "create" || result.action === "supersede") notify("membership");
|
|
24417
|
+
else if (result.action === "update" || result.action === "merge") notify("edit");
|
|
24418
|
+
return result;
|
|
24419
|
+
},
|
|
24420
|
+
subscribe: (onChange, subscribeOptions = {}) => {
|
|
24421
|
+
const subscriber = { onChange, options: subscribeOptions };
|
|
24422
|
+
subscribers.add(subscriber);
|
|
24423
|
+
if (pollIntervalMs > 0 && !timer) {
|
|
24424
|
+
timer = setInterval(poll, pollIntervalMs);
|
|
24425
|
+
poll();
|
|
24426
|
+
}
|
|
24427
|
+
return () => {
|
|
24428
|
+
subscribers.delete(subscriber);
|
|
24429
|
+
if (subscribers.size || !timer) return;
|
|
24430
|
+
clearInterval(timer);
|
|
24431
|
+
timer = void 0;
|
|
24432
|
+
generation++;
|
|
24433
|
+
seen.clear();
|
|
24434
|
+
ready = false;
|
|
24435
|
+
cursor = void 0;
|
|
24436
|
+
pending = /* @__PURE__ */ new Set();
|
|
24437
|
+
};
|
|
24438
|
+
}
|
|
24439
|
+
};
|
|
24440
|
+
}
|
|
24441
|
+
|
|
23645
24442
|
// src/lib/memory/synthesizeProfile.ts
|
|
23646
24443
|
init_internalFlowMarker();
|
|
23647
24444
|
init_logger();
|
|
@@ -37621,7 +38418,11 @@ function useWalletBinding(options = {}) {
|
|
|
37621
38418
|
LoggerProvider,
|
|
37622
38419
|
MAX_HOPS,
|
|
37623
38420
|
MEDIUM_TTL_MS,
|
|
38421
|
+
MEMORY_KINDS,
|
|
38422
|
+
MEMORY_LEVELS,
|
|
37624
38423
|
MemoryEntityModel,
|
|
38424
|
+
MemoryKeyError,
|
|
38425
|
+
MemoryLevelError,
|
|
37625
38426
|
NEVER_TTL_MS,
|
|
37626
38427
|
NODE_BUDGET,
|
|
37627
38428
|
PAST_EVENT_GRACE_MS,
|
|
@@ -37635,6 +38436,7 @@ function useWalletBinding(options = {}) {
|
|
|
37635
38436
|
RECALL_MAX_LIMIT,
|
|
37636
38437
|
RECALL_TOOL_NAME,
|
|
37637
38438
|
RemoteMemoryError,
|
|
38439
|
+
RemoteMemoryPartialCreateError,
|
|
37638
38440
|
RerankerUnavailableError,
|
|
37639
38441
|
SDK_SCHEMA_VERSION,
|
|
37640
38442
|
SERVER_TOOL_DEPENDENCY_SETS,
|
|
@@ -37728,6 +38530,7 @@ function useWalletBinding(options = {}) {
|
|
|
37728
38530
|
createRecallTool,
|
|
37729
38531
|
createRemoteMemoryPersistence,
|
|
37730
38532
|
createRemoteMemoryPipeline,
|
|
38533
|
+
createRemoteMemoryStore,
|
|
37731
38534
|
createSavedToolOp,
|
|
37732
38535
|
createServerToolsFilter,
|
|
37733
38536
|
createStockPricePreProcessor,
|
|
@@ -37759,6 +38562,7 @@ function useWalletBinding(options = {}) {
|
|
|
37759
38562
|
deleteVaultMemoryOp,
|
|
37760
38563
|
dequantizeEmbedding,
|
|
37761
38564
|
deriveKeyFromSignatureBytes,
|
|
38565
|
+
deriveMemoryKeyRing,
|
|
37762
38566
|
eagerEmbedContent,
|
|
37763
38567
|
embedAllMessages,
|
|
37764
38568
|
embedMessage,
|
|
@@ -37898,6 +38702,7 @@ function useWalletBinding(options = {}) {
|
|
|
37898
38702
|
linkMemoryEntitiesOp,
|
|
37899
38703
|
maskScopedEmbeddingCache,
|
|
37900
38704
|
mediaToStored,
|
|
38705
|
+
memoryCipher,
|
|
37901
38706
|
migrateCalendarToken,
|
|
37902
38707
|
migrateDisplayResult,
|
|
37903
38708
|
migrateDriveToken,
|
|
@@ -37919,6 +38724,7 @@ function useWalletBinding(options = {}) {
|
|
|
37919
38724
|
rankProfileCandidates,
|
|
37920
38725
|
readEncryptedFile,
|
|
37921
38726
|
recall,
|
|
38727
|
+
reencryptMemoryField,
|
|
37922
38728
|
reflect,
|
|
37923
38729
|
refreshCalendarToken,
|
|
37924
38730
|
refreshDriveToken,
|