@anuma/sdk 7.0.3 → 7.0.4-next.20261015010856
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 +288 -73
- package/dist/expo/index.d.mts +24 -4
- package/dist/expo/index.d.ts +24 -4
- package/dist/expo/index.mjs +288 -73
- package/dist/memory/context.d.mts +1 -0
- package/dist/memory/context.d.ts +1 -0
- package/dist/react/index.cjs +293 -73
- package/dist/react/index.d.mts +24 -4
- package/dist/react/index.d.ts +24 -4
- package/dist/react/index.mjs +293 -73
- package/dist/server/index.cjs +237 -33
- package/dist/server/index.d.mts +26 -3
- package/dist/server/index.d.ts +26 -3
- package/dist/server/index.mjs +237 -33
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -4456,8 +4456,9 @@ async function getConversationsByProjectOp(ctx, projectId) {
|
|
|
4456
4456
|
)
|
|
4457
4457
|
);
|
|
4458
4458
|
}
|
|
4459
|
-
async function getMessagesOp(ctx, convId) {
|
|
4460
|
-
const
|
|
4459
|
+
async function getMessagesOp(ctx, convId, opts) {
|
|
4460
|
+
const fetched = await ctx.messagesCollection.query(import_watermelondb2.Q.where("conversation_id", convId), import_watermelondb2.Q.sortBy("message_id", import_watermelondb2.Q.asc)).unsafeFetchRaw();
|
|
4461
|
+
const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
|
|
4461
4462
|
return Promise.all(
|
|
4462
4463
|
results.map(
|
|
4463
4464
|
(raw) => messageRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
@@ -6708,6 +6709,37 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
|
|
|
6708
6709
|
}));
|
|
6709
6710
|
return updateMessageChunksOp(ctx, messageId, messageChunks, embeddingModel);
|
|
6710
6711
|
}
|
|
6712
|
+
var MIN_SEALED_EMBEDDING_HEX = 256;
|
|
6713
|
+
function rawHasEmbedding(value) {
|
|
6714
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
6715
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
6716
|
+
if (isEncrypted(value)) {
|
|
6717
|
+
return value.length - value.indexOf(":", 4) - 1 >= MIN_SEALED_EMBEDDING_HEX;
|
|
6718
|
+
}
|
|
6719
|
+
try {
|
|
6720
|
+
const parsed = JSON.parse(value);
|
|
6721
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
6722
|
+
} catch {
|
|
6723
|
+
return false;
|
|
6724
|
+
}
|
|
6725
|
+
}
|
|
6726
|
+
function sealedVersion(value) {
|
|
6727
|
+
if (typeof value !== "string" || !isEncrypted(value)) return null;
|
|
6728
|
+
return value.startsWith("enc:v2:") ? "v2" : "v3";
|
|
6729
|
+
}
|
|
6730
|
+
function mayNeedChunkEmbedding(raw, embeddingModel, filter) {
|
|
6731
|
+
const role = raw.role;
|
|
6732
|
+
if (role === "system") return false;
|
|
6733
|
+
if (filter?.roles && !filter.roles.includes(role ?? "")) return false;
|
|
6734
|
+
if (isNonEmbeddableOrigin(raw.origin, filter?.reembedDiscarded)) {
|
|
6735
|
+
return false;
|
|
6736
|
+
}
|
|
6737
|
+
const model = raw.embedding_model;
|
|
6738
|
+
if (typeof model === "string" && model !== embeddingModel) return true;
|
|
6739
|
+
if (rawHasEmbedding(raw.chunks)) return false;
|
|
6740
|
+
if (rawHasEmbedding(raw.vector) && !filter?.rechunkExisting) return false;
|
|
6741
|
+
return true;
|
|
6742
|
+
}
|
|
6711
6743
|
async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
6712
6744
|
const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
6713
6745
|
const { chunkSize = DEFAULT_CHUNK_SIZE } = options;
|
|
@@ -6720,11 +6752,31 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
6720
6752
|
let considered = 0;
|
|
6721
6753
|
let sealedRowsSeen = 0;
|
|
6722
6754
|
let rowsSeen = 0;
|
|
6755
|
+
const keptSealed = /* @__PURE__ */ new Map();
|
|
6756
|
+
const candidatesStillSealed = /* @__PURE__ */ new Map();
|
|
6757
|
+
const droppedSealed = /* @__PURE__ */ new Map();
|
|
6758
|
+
const rawFilter = (raw) => {
|
|
6759
|
+
rowsSeen++;
|
|
6760
|
+
const keep = mayNeedChunkEmbedding(raw, embeddingModel, filter);
|
|
6761
|
+
const version = sealedVersion(raw.content);
|
|
6762
|
+
if (!version) return keep;
|
|
6763
|
+
if (keep) {
|
|
6764
|
+
keptSealed.set(version, (keptSealed.get(version) ?? 0) + 1);
|
|
6765
|
+
} else {
|
|
6766
|
+
const dropped = droppedSealed.get(version);
|
|
6767
|
+
if (dropped) dropped.count++;
|
|
6768
|
+
else droppedSealed.set(version, { count: 1, probeId: raw.id });
|
|
6769
|
+
}
|
|
6770
|
+
return keep;
|
|
6771
|
+
};
|
|
6723
6772
|
for (const conv of targetConversations) {
|
|
6724
|
-
const messages = await getMessagesOp(ctx, conv.conversationId);
|
|
6773
|
+
const messages = await getMessagesOp(ctx, conv.conversationId, { rawFilter });
|
|
6725
6774
|
for (const message of messages) {
|
|
6726
|
-
|
|
6727
|
-
if (
|
|
6775
|
+
const stillSealed = sealedVersion(message.content);
|
|
6776
|
+
if (stillSealed) {
|
|
6777
|
+
sealedRowsSeen++;
|
|
6778
|
+
candidatesStillSealed.set(stillSealed, (candidatesStillSealed.get(stillSealed) ?? 0) + 1);
|
|
6779
|
+
}
|
|
6728
6780
|
const isStale = message.embeddingModel !== void 0 && message.embeddingModel !== null && message.embeddingModel !== embeddingModel;
|
|
6729
6781
|
if (message.chunks && message.chunks.length > 0 && !isStale) continue;
|
|
6730
6782
|
const hasVector = message.vector && message.vector.length > 0;
|
|
@@ -6737,6 +6789,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
6737
6789
|
stillEncrypted++;
|
|
6738
6790
|
continue;
|
|
6739
6791
|
}
|
|
6792
|
+
if (isToolResultsRow(message)) continue;
|
|
6740
6793
|
if (message.content.length < minLength) continue;
|
|
6741
6794
|
if (shouldChunkMessage(message.content, chunkSize)) {
|
|
6742
6795
|
longMessages.push({
|
|
@@ -6748,6 +6801,12 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
6748
6801
|
}
|
|
6749
6802
|
}
|
|
6750
6803
|
}
|
|
6804
|
+
for (const [version, dropped] of droppedSealed) {
|
|
6805
|
+
const keyOpenedACandidate = (keptSealed.get(version) ?? 0) > (candidatesStillSealed.get(version) ?? 0);
|
|
6806
|
+
if (keyOpenedACandidate) continue;
|
|
6807
|
+
const probe = await getMessageOp(ctx, dropped.probeId);
|
|
6808
|
+
if (!probe || isEncrypted(probe.content)) sealedRowsSeen += dropped.count;
|
|
6809
|
+
}
|
|
6751
6810
|
if (stillEncrypted > 0 || sealedRowsSeen > 0) {
|
|
6752
6811
|
getLogger().error(
|
|
6753
6812
|
"memoryEngine: messages still encrypted (key unavailable?) \u2014 excluded from embedding",
|
|
@@ -12209,6 +12268,11 @@ function parseTopics(value) {
|
|
|
12209
12268
|
}
|
|
12210
12269
|
|
|
12211
12270
|
// src/lib/db/entities/operations.ts
|
|
12271
|
+
async function assertCanWrite(ctx) {
|
|
12272
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
12273
|
+
throw new Error("Memory source is no longer eligible");
|
|
12274
|
+
}
|
|
12275
|
+
}
|
|
12212
12276
|
function entityToStored(e) {
|
|
12213
12277
|
return {
|
|
12214
12278
|
uniqueId: e.id,
|
|
@@ -12349,6 +12413,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
12349
12413
|
let skipped = false;
|
|
12350
12414
|
let entities = [];
|
|
12351
12415
|
await ctx.database.write(async () => {
|
|
12416
|
+
await assertCanWrite(ctx);
|
|
12352
12417
|
const {
|
|
12353
12418
|
entities: byName,
|
|
12354
12419
|
operations: entityOps,
|
|
@@ -12424,6 +12489,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
12424
12489
|
let skipped = false;
|
|
12425
12490
|
let entities = [];
|
|
12426
12491
|
await ctx.database.write(async () => {
|
|
12492
|
+
await assertCanWrite(ctx);
|
|
12427
12493
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
12428
12494
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
12429
12495
|
skipped = true;
|
|
@@ -12484,6 +12550,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
12484
12550
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb11.Q.where("memory_id", import_watermelondb11.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
12485
12551
|
if (links.length === 0) return;
|
|
12486
12552
|
await ctx.database.write(async () => {
|
|
12553
|
+
await assertCanWrite(ctx);
|
|
12487
12554
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
12488
12555
|
});
|
|
12489
12556
|
}
|
|
@@ -12492,6 +12559,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
12492
12559
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb11.Q.where("user_id", userId)).fetch();
|
|
12493
12560
|
if (links.length === 0) return;
|
|
12494
12561
|
await ctx.database.write(async () => {
|
|
12562
|
+
await assertCanWrite(ctx);
|
|
12495
12563
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
12496
12564
|
});
|
|
12497
12565
|
}
|
|
@@ -12511,6 +12579,7 @@ async function backfillMemoryEntityUserIdsOp(ctx, vaultMemoryCollection) {
|
|
|
12511
12579
|
}
|
|
12512
12580
|
if (toUpdate.length === 0) return 0;
|
|
12513
12581
|
await ctx.database.write(async () => {
|
|
12582
|
+
await assertCanWrite(ctx);
|
|
12514
12583
|
await ctx.database.batch(
|
|
12515
12584
|
...toUpdate.map(({ link, userId }) => link.prepareUpdate((r) => r._setRaw("user_id", userId)))
|
|
12516
12585
|
);
|
|
@@ -14904,6 +14973,11 @@ function visibilityConditions(requested) {
|
|
|
14904
14973
|
function isKinded(record2) {
|
|
14905
14974
|
return record2.kind !== null && record2.kind !== void 0;
|
|
14906
14975
|
}
|
|
14976
|
+
async function assertCanWrite2(ctx) {
|
|
14977
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
14978
|
+
throw new Error("Memory source is no longer eligible");
|
|
14979
|
+
}
|
|
14980
|
+
}
|
|
14907
14981
|
function assertValidKindLevel(kind, level) {
|
|
14908
14982
|
const hasKind = kind !== null && kind !== void 0;
|
|
14909
14983
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -15084,8 +15158,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
15084
15158
|
ctx.embeddedWalletSigner
|
|
15085
15159
|
) : opts.content;
|
|
15086
15160
|
const created = await ctx.database.write(async () => {
|
|
15087
|
-
|
|
15088
|
-
throw new Error("Memory source is no longer eligible");
|
|
15161
|
+
await assertCanWrite2(ctx);
|
|
15089
15162
|
return ctx.vaultMemoryCollection.create(
|
|
15090
15163
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
15091
15164
|
);
|
|
@@ -15104,8 +15177,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
15104
15177
|
) : opts.content;
|
|
15105
15178
|
let createdRecord = null;
|
|
15106
15179
|
await ctx.database.write(async () => {
|
|
15107
|
-
|
|
15108
|
-
throw new Error("Memory source is no longer eligible");
|
|
15180
|
+
await assertCanWrite2(ctx);
|
|
15109
15181
|
let target;
|
|
15110
15182
|
try {
|
|
15111
15183
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -15197,8 +15269,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
15197
15269
|
})
|
|
15198
15270
|
);
|
|
15199
15271
|
const created = await ctx.database.write(async () => {
|
|
15200
|
-
|
|
15201
|
-
throw new Error("Memory source is no longer eligible");
|
|
15272
|
+
await assertCanWrite2(ctx);
|
|
15202
15273
|
const prepared = optionsArray.map(
|
|
15203
15274
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
15204
15275
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -15503,8 +15574,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
15503
15574
|
const record2 = probe;
|
|
15504
15575
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15505
15576
|
await ctx.database.write(async () => {
|
|
15506
|
-
|
|
15507
|
-
throw new Error("Memory source is no longer eligible");
|
|
15577
|
+
await assertCanWrite2(ctx);
|
|
15508
15578
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
15509
15579
|
stale = true;
|
|
15510
15580
|
return;
|
|
@@ -15615,6 +15685,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
15615
15685
|
let stale = false;
|
|
15616
15686
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15617
15687
|
await ctx.database.write(async (writer) => {
|
|
15688
|
+
await assertCanWrite2(ctx);
|
|
15618
15689
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15619
15690
|
stale = true;
|
|
15620
15691
|
return;
|
|
@@ -15656,6 +15727,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
15656
15727
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
15657
15728
|
let cleared = false;
|
|
15658
15729
|
await ctx.database.write(async () => {
|
|
15730
|
+
await assertCanWrite2(ctx);
|
|
15659
15731
|
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
15660
15732
|
cleared = true;
|
|
15661
15733
|
await record2.update((r) => {
|
|
@@ -15679,6 +15751,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
15679
15751
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
15680
15752
|
let stale = false;
|
|
15681
15753
|
await ctx.database.write(async () => {
|
|
15754
|
+
await assertCanWrite2(ctx);
|
|
15682
15755
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15683
15756
|
stale = true;
|
|
15684
15757
|
return;
|
|
@@ -15707,6 +15780,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
15707
15780
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
15708
15781
|
let stale = false;
|
|
15709
15782
|
await ctx.database.write(async () => {
|
|
15783
|
+
await assertCanWrite2(ctx);
|
|
15710
15784
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
15711
15785
|
stale = true;
|
|
15712
15786
|
return;
|
|
@@ -15744,8 +15818,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
15744
15818
|
}
|
|
15745
15819
|
let stale = false;
|
|
15746
15820
|
await ctx.database.write(async () => {
|
|
15747
|
-
|
|
15748
|
-
throw new Error("Memory source is no longer eligible");
|
|
15821
|
+
await assertCanWrite2(ctx);
|
|
15749
15822
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
15750
15823
|
stale = true;
|
|
15751
15824
|
return;
|
|
@@ -15907,6 +15980,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
15907
15980
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
15908
15981
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
15909
15982
|
await ctx.database.write(async () => {
|
|
15983
|
+
await assertCanWrite2(ctx);
|
|
15910
15984
|
const records = [];
|
|
15911
15985
|
for (const id of chunkIds) {
|
|
15912
15986
|
try {
|
|
@@ -15940,6 +16014,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
15940
16014
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
15941
16015
|
try {
|
|
15942
16016
|
await ctx.database.write(async (writer) => {
|
|
16017
|
+
await assertCanWrite2(ctx);
|
|
15943
16018
|
let record2;
|
|
15944
16019
|
try {
|
|
15945
16020
|
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -15970,6 +16045,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
15970
16045
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
15971
16046
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
15972
16047
|
await ctx.database.write(async () => {
|
|
16048
|
+
await assertCanWrite2(ctx);
|
|
15973
16049
|
const writes = [];
|
|
15974
16050
|
for (const id of chunkIds) {
|
|
15975
16051
|
let record2;
|
|
@@ -16002,6 +16078,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
16002
16078
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb23.Q.where("user_id", userId), import_watermelondb23.Q.where("is_deleted", false)).fetch();
|
|
16003
16079
|
if (records.length === 0) return 0;
|
|
16004
16080
|
await ctx.database.write(async () => {
|
|
16081
|
+
await assertCanWrite2(ctx);
|
|
16005
16082
|
const prepared = records.map(
|
|
16006
16083
|
(record2) => record2.prepareUpdate((r) => {
|
|
16007
16084
|
r._setRaw("is_deleted", true);
|
|
@@ -16056,6 +16133,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
16056
16133
|
let stale = false;
|
|
16057
16134
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
16058
16135
|
await ctx.database.write(async () => {
|
|
16136
|
+
await assertCanWrite2(ctx);
|
|
16059
16137
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
16060
16138
|
stale = true;
|
|
16061
16139
|
return;
|
|
@@ -16079,6 +16157,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
16079
16157
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
16080
16158
|
let stale = false;
|
|
16081
16159
|
await ctx.database.write(async () => {
|
|
16160
|
+
await assertCanWrite2(ctx);
|
|
16082
16161
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
16083
16162
|
stale = true;
|
|
16084
16163
|
return;
|
|
@@ -16099,6 +16178,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
16099
16178
|
const now = opts.now ?? Date.now();
|
|
16100
16179
|
let stale = false;
|
|
16101
16180
|
await ctx.database.write(async () => {
|
|
16181
|
+
await assertCanWrite2(ctx);
|
|
16102
16182
|
const archivedAt = record2.archivedAt;
|
|
16103
16183
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
16104
16184
|
stale = true;
|
|
@@ -16138,6 +16218,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
|
|
|
16138
16218
|
}
|
|
16139
16219
|
let written = false;
|
|
16140
16220
|
await ctx.database.write(async () => {
|
|
16221
|
+
await assertCanWrite2(ctx);
|
|
16141
16222
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
16142
16223
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
16143
16224
|
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
@@ -20134,6 +20215,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
20134
20215
|
).map((c) => c.candidate);
|
|
20135
20216
|
}
|
|
20136
20217
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
20218
|
+
const { memoryStore, signal } = options;
|
|
20219
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
20220
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
20221
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
20222
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
20223
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
20224
|
+
signal?.throwIfAborted();
|
|
20137
20225
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
20138
20226
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
20139
20227
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -20167,6 +20255,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
20167
20255
|
}
|
|
20168
20256
|
});
|
|
20169
20257
|
const extractMs = Date.now() - tExtract;
|
|
20258
|
+
signal?.throwIfAborted();
|
|
20170
20259
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
20171
20260
|
const log = getLogger();
|
|
20172
20261
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -20214,16 +20303,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
20214
20303
|
const results = [];
|
|
20215
20304
|
const quarantinedInfo = [];
|
|
20216
20305
|
let failedWrites = 0;
|
|
20306
|
+
let auditRows;
|
|
20217
20307
|
const tRetain = Date.now();
|
|
20218
20308
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
20219
20309
|
try {
|
|
20310
|
+
signal?.throwIfAborted();
|
|
20220
20311
|
if (isQuarantined) {
|
|
20221
|
-
|
|
20222
|
-
|
|
20223
|
-
|
|
20224
|
-
|
|
20225
|
-
|
|
20226
|
-
|
|
20312
|
+
let existingId;
|
|
20313
|
+
if (memoryStore) {
|
|
20314
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
20315
|
+
scopes: [options.scope ?? "private"],
|
|
20316
|
+
includeArchived: true,
|
|
20317
|
+
includeQuarantined: true,
|
|
20318
|
+
includeSuperseded: true
|
|
20319
|
+
}));
|
|
20320
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
20321
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
20322
|
+
existingId = (await auditRows).find(
|
|
20323
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
20324
|
+
)?.uniqueId ?? null;
|
|
20325
|
+
} else {
|
|
20326
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
20327
|
+
retainCtx.vaultCtx,
|
|
20328
|
+
candidate.content,
|
|
20329
|
+
candidate.sourceMessageIds,
|
|
20330
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
20331
|
+
).catch(() => null);
|
|
20332
|
+
}
|
|
20227
20333
|
if (existingId) {
|
|
20228
20334
|
quarantinedInfo.push({
|
|
20229
20335
|
candidate,
|
|
@@ -20234,18 +20340,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
20234
20340
|
continue;
|
|
20235
20341
|
}
|
|
20236
20342
|
}
|
|
20237
|
-
const
|
|
20343
|
+
const retainOptions = {
|
|
20238
20344
|
source: "auto-extracted",
|
|
20239
20345
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
20240
20346
|
respectTombstones: true,
|
|
20241
20347
|
...options.scope !== void 0 && { scope: options.scope },
|
|
20242
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
20243
20348
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
20244
20349
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
20245
20350
|
factType: candidate.type,
|
|
20246
20351
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
20352
|
+
};
|
|
20353
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
20354
|
+
...retainOptions,
|
|
20355
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
20356
|
+
signal
|
|
20357
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
20358
|
+
...retainOptions,
|
|
20359
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
20247
20360
|
});
|
|
20248
20361
|
if (isQuarantined) {
|
|
20362
|
+
auditRows = void 0;
|
|
20249
20363
|
const info = {
|
|
20250
20364
|
candidate,
|
|
20251
20365
|
memoryId: result.memoryId,
|
|
@@ -20264,9 +20378,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
20264
20378
|
}
|
|
20265
20379
|
succeededCandidates.push(candidate);
|
|
20266
20380
|
results.push(result);
|
|
20267
|
-
if (result.action !== "suppressed" &&
|
|
20381
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
20268
20382
|
try {
|
|
20269
|
-
|
|
20383
|
+
signal?.throwIfAborted();
|
|
20384
|
+
if (memoryStore) {
|
|
20385
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
20386
|
+
unlessUserManaged: true,
|
|
20387
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
20388
|
+
signal
|
|
20389
|
+
});
|
|
20390
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
20270
20391
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
20271
20392
|
unlessTopicsUserManaged: true
|
|
20272
20393
|
});
|
|
@@ -20516,7 +20637,7 @@ function createAutoExtractor(options) {
|
|
|
20516
20637
|
};
|
|
20517
20638
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
20518
20639
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
20519
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
20640
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
20520
20641
|
getLogger().warn(
|
|
20521
20642
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
20522
20643
|
);
|
|
@@ -20561,6 +20682,8 @@ function createAutoExtractor(options) {
|
|
|
20561
20682
|
try {
|
|
20562
20683
|
const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
20563
20684
|
extract,
|
|
20685
|
+
memoryStore: options.memoryStore,
|
|
20686
|
+
signal: options.signal,
|
|
20564
20687
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
20565
20688
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
20566
20689
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -22688,6 +22811,7 @@ function createLocalMemoryStore(options) {
|
|
|
22688
22811
|
database,
|
|
22689
22812
|
entityCollection: database.get("entity"),
|
|
22690
22813
|
memoryEntityCollection: database.get("memory_entity"),
|
|
22814
|
+
canWrite: options.canWrite,
|
|
22691
22815
|
...userId !== void 0 && { userId },
|
|
22692
22816
|
...options.allowUnscopedRows !== void 0 && {
|
|
22693
22817
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -22699,10 +22823,21 @@ function createLocalMemoryStore(options) {
|
|
|
22699
22823
|
walletAddress: options.walletAddress,
|
|
22700
22824
|
signMessage: options.signMessage,
|
|
22701
22825
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
22826
|
+
canWrite: options.canWrite,
|
|
22702
22827
|
...userId !== void 0 && { userId },
|
|
22703
22828
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
22704
22829
|
entityCtx
|
|
22705
22830
|
};
|
|
22831
|
+
const assertWrite = async (writeOptions) => {
|
|
22832
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22833
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
22834
|
+
throw new Error("Memory source is no longer eligible");
|
|
22835
|
+
}
|
|
22836
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
22837
|
+
throw new Error("Memory source is no longer eligible");
|
|
22838
|
+
}
|
|
22839
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22840
|
+
};
|
|
22706
22841
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
22707
22842
|
const ownedBy = userId !== void 0 ? [import_watermelondb32.Q.where("user_id", userId)] : [];
|
|
22708
22843
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb32.Q.or(import_watermelondb32.Q.where("user_id", userId), import_watermelondb32.Q.where("user_id", null))] : [import_watermelondb32.Q.where("user_id", userId)];
|
|
@@ -22814,9 +22949,25 @@ function createLocalMemoryStore(options) {
|
|
|
22814
22949
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
22815
22950
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
22816
22951
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
22817
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
22952
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
22953
|
+
await assertWrite(writeOptions);
|
|
22818
22954
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb32.Q.where("id", memoryId), import_watermelondb32.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
22819
|
-
return owned > 0 ? writer.callWriter(
|
|
22955
|
+
return owned > 0 ? writer.callWriter(
|
|
22956
|
+
() => linkMemoryEntitiesOp(
|
|
22957
|
+
{
|
|
22958
|
+
...entityCtx,
|
|
22959
|
+
canWrite: async () => {
|
|
22960
|
+
await assertWrite(writeOptions);
|
|
22961
|
+
return true;
|
|
22962
|
+
}
|
|
22963
|
+
},
|
|
22964
|
+
memoryId,
|
|
22965
|
+
topics,
|
|
22966
|
+
{
|
|
22967
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
22968
|
+
}
|
|
22969
|
+
)
|
|
22970
|
+
) : [];
|
|
22820
22971
|
}),
|
|
22821
22972
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
22822
22973
|
recall: (query, recallOptions) => recall(
|
|
@@ -22826,7 +22977,17 @@ function createLocalMemoryStore(options) {
|
|
|
22826
22977
|
),
|
|
22827
22978
|
retain: (content, retainOptions) => retain(
|
|
22828
22979
|
content,
|
|
22829
|
-
{
|
|
22980
|
+
{
|
|
22981
|
+
vaultCtx: {
|
|
22982
|
+
...vaultCtx,
|
|
22983
|
+
canWrite: async () => {
|
|
22984
|
+
await assertWrite(retainOptions);
|
|
22985
|
+
return true;
|
|
22986
|
+
}
|
|
22987
|
+
},
|
|
22988
|
+
embeddingOptions: options.embeddingOptions,
|
|
22989
|
+
vaultCache
|
|
22990
|
+
},
|
|
22830
22991
|
retainOptions
|
|
22831
22992
|
),
|
|
22832
22993
|
factSource: {
|
|
@@ -23465,7 +23626,14 @@ function stored(row) {
|
|
|
23465
23626
|
function createRemoteMemoryPipeline(options) {
|
|
23466
23627
|
const { persistence, embeddingOptions } = options;
|
|
23467
23628
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
23468
|
-
const operation = (mode) => {
|
|
23629
|
+
const operation = (mode, writeOptions) => {
|
|
23630
|
+
const signal = writeOptions?.signal;
|
|
23631
|
+
const assertWrite = async () => {
|
|
23632
|
+
signal?.throwIfAborted();
|
|
23633
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
23634
|
+
throw new Error("Memory source is no longer eligible");
|
|
23635
|
+
signal?.throwIfAborted();
|
|
23636
|
+
};
|
|
23469
23637
|
const rejectUndecryptable = (failed) => {
|
|
23470
23638
|
if (!failed.length) return;
|
|
23471
23639
|
if (mode === "retain")
|
|
@@ -23483,7 +23651,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23483
23651
|
return items.map((item) => stored(item.memory));
|
|
23484
23652
|
};
|
|
23485
23653
|
const get = async (id) => {
|
|
23486
|
-
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
23654
|
+
const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
23487
23655
|
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
23488
23656
|
snapshots.set(id, snapshot);
|
|
23489
23657
|
return stored(snapshot.memory);
|
|
@@ -23529,7 +23697,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23529
23697
|
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
23530
23698
|
}
|
|
23531
23699
|
const forceIds = [...forced];
|
|
23532
|
-
const windowOptions = (i,
|
|
23700
|
+
const windowOptions = (i, signal2) => ({
|
|
23533
23701
|
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
23534
23702
|
force_ids: i === 0 ? forceIds : [],
|
|
23535
23703
|
...search.scopes && { scopes: search.scopes },
|
|
@@ -23537,13 +23705,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23537
23705
|
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
23538
23706
|
include_archived: search.includeArchived,
|
|
23539
23707
|
embedding_model: model,
|
|
23540
|
-
...
|
|
23708
|
+
...signal2 && { signal: signal2 }
|
|
23541
23709
|
});
|
|
23542
23710
|
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
23543
23711
|
let windows;
|
|
23544
23712
|
if (mode === "retain") {
|
|
23545
23713
|
windows = await Promise.all(
|
|
23546
|
-
vectors.map(
|
|
23714
|
+
vectors.map(
|
|
23715
|
+
(embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
|
|
23716
|
+
)
|
|
23547
23717
|
);
|
|
23548
23718
|
} else {
|
|
23549
23719
|
const deadline = new AbortController();
|
|
@@ -23631,12 +23801,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23631
23801
|
twin_opt_in: false
|
|
23632
23802
|
};
|
|
23633
23803
|
};
|
|
23634
|
-
const write = async (memory, snapshot) =>
|
|
23804
|
+
const write = async (memory, snapshot) => {
|
|
23805
|
+
await assertWrite();
|
|
23806
|
+
return remember([await persistence.put(memory, snapshot, signal)])[0];
|
|
23807
|
+
};
|
|
23635
23808
|
const port = {
|
|
23636
23809
|
prepare,
|
|
23637
23810
|
get,
|
|
23638
23811
|
getFresh: async (id) => {
|
|
23639
|
-
const current = await persistence.get(id);
|
|
23812
|
+
const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
23640
23813
|
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
23641
23814
|
},
|
|
23642
23815
|
tombstones: async (embedding2, embeddingModel, scope, folderId) => {
|
|
@@ -23647,7 +23820,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23647
23820
|
embedding_model: embeddingModel,
|
|
23648
23821
|
strict_model: true,
|
|
23649
23822
|
include_deleted: true,
|
|
23650
|
-
deleted_only: true
|
|
23823
|
+
deleted_only: true,
|
|
23824
|
+
signal
|
|
23651
23825
|
});
|
|
23652
23826
|
rejectUndecryptable(window2.failed);
|
|
23653
23827
|
return remember(window2.items);
|
|
@@ -23703,14 +23877,18 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23703
23877
|
if (!target || !newer || id === successor) return false;
|
|
23704
23878
|
const old = snapshots.get(id);
|
|
23705
23879
|
const next = snapshots.get(successor);
|
|
23880
|
+
await assertWrite();
|
|
23706
23881
|
remember(
|
|
23707
|
-
await persistence.putMany(
|
|
23708
|
-
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23882
|
+
await persistence.putMany(
|
|
23883
|
+
[
|
|
23884
|
+
{
|
|
23885
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
23886
|
+
expectedVersion: old
|
|
23887
|
+
},
|
|
23888
|
+
{ memory: next.memory, expectedVersion: next }
|
|
23889
|
+
],
|
|
23890
|
+
signal
|
|
23891
|
+
)
|
|
23714
23892
|
);
|
|
23715
23893
|
return true;
|
|
23716
23894
|
},
|
|
@@ -23719,18 +23897,22 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23719
23897
|
if (!target) return { created: null, retired: false };
|
|
23720
23898
|
const snapshot = snapshots.get(targetId);
|
|
23721
23899
|
const successor = createRow(input);
|
|
23900
|
+
await assertWrite();
|
|
23722
23901
|
const rows = remember(
|
|
23723
|
-
await persistence.putMany(
|
|
23724
|
-
|
|
23725
|
-
|
|
23726
|
-
|
|
23727
|
-
|
|
23728
|
-
|
|
23729
|
-
|
|
23730
|
-
|
|
23731
|
-
|
|
23732
|
-
|
|
23733
|
-
|
|
23902
|
+
await persistence.putMany(
|
|
23903
|
+
[
|
|
23904
|
+
{ memory: successor, expectedVersion: 0 },
|
|
23905
|
+
{
|
|
23906
|
+
memory: {
|
|
23907
|
+
...snapshot.memory,
|
|
23908
|
+
superseded_by: successor.memory_id,
|
|
23909
|
+
superseded_at: Date.now()
|
|
23910
|
+
},
|
|
23911
|
+
expectedVersion: snapshot
|
|
23912
|
+
}
|
|
23913
|
+
],
|
|
23914
|
+
signal
|
|
23915
|
+
)
|
|
23734
23916
|
);
|
|
23735
23917
|
return { created: rows[0], retired: true };
|
|
23736
23918
|
}
|
|
@@ -23763,7 +23945,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
23763
23945
|
factSource,
|
|
23764
23946
|
recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
|
|
23765
23947
|
retain: async (content, retainOptions) => {
|
|
23766
|
-
const { port } = operation("retain");
|
|
23948
|
+
const { port } = operation("retain", retainOptions);
|
|
23767
23949
|
return retainWithPersistence(
|
|
23768
23950
|
content,
|
|
23769
23951
|
{
|
|
@@ -24346,16 +24528,21 @@ function createRemoteMemoryStore(options) {
|
|
|
24346
24528
|
const record2 = await persistence.get(id);
|
|
24347
24529
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
24348
24530
|
};
|
|
24349
|
-
const mutateLocked = async (id, change, edit) => {
|
|
24350
|
-
|
|
24531
|
+
const mutateLocked = async (id, change, edit, writeOptions) => {
|
|
24532
|
+
writeOptions?.signal?.throwIfAborted();
|
|
24533
|
+
const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
|
|
24351
24534
|
if (!record2) return null;
|
|
24535
|
+
if (record2.memory.is_deleted) return null;
|
|
24536
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
24537
|
+
throw new Error("Memory source is no longer eligible");
|
|
24538
|
+
writeOptions?.signal?.throwIfAborted();
|
|
24352
24539
|
const next = edit(structuredClone(record2.memory));
|
|
24353
24540
|
if (!next) return null;
|
|
24354
|
-
const saved = await persistence.put(next, record2);
|
|
24541
|
+
const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
|
|
24355
24542
|
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
24356
24543
|
return saved;
|
|
24357
24544
|
};
|
|
24358
|
-
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
24545
|
+
const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
|
|
24359
24546
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
24360
24547
|
const mutateMany = async (ids, change, edit) => {
|
|
24361
24548
|
const saved = /* @__PURE__ */ new Map();
|
|
@@ -24868,13 +25055,21 @@ function createRemoteMemoryStore(options) {
|
|
|
24868
25055
|
}))
|
|
24869
25056
|
);
|
|
24870
25057
|
},
|
|
24871
|
-
addTopics: async (memoryId, topics) => {
|
|
25058
|
+
addTopics: async (memoryId, topics, writeOptions) => {
|
|
24872
25059
|
const added = await withKnownKinds(topicInputs(topics, "auto"));
|
|
24873
|
-
const saved = await mutate(
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
25060
|
+
const saved = await mutate(
|
|
25061
|
+
memoryId,
|
|
25062
|
+
"edit",
|
|
25063
|
+
(memory) => {
|
|
25064
|
+
if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
|
|
25065
|
+
return {
|
|
25066
|
+
...memory,
|
|
25067
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
25068
|
+
topics_updated_at: Date.now()
|
|
25069
|
+
};
|
|
25070
|
+
},
|
|
25071
|
+
writeOptions
|
|
25072
|
+
);
|
|
24878
25073
|
if (!saved) return [];
|
|
24879
25074
|
const now = /* @__PURE__ */ new Date();
|
|
24880
25075
|
return mergeTopics([], added).map(
|
|
@@ -25727,6 +25922,7 @@ function createDurableAutoExtractor(options) {
|
|
|
25727
25922
|
};
|
|
25728
25923
|
const folderId = options.folderId ?? null;
|
|
25729
25924
|
let disposed = false;
|
|
25925
|
+
let activeBatch = null;
|
|
25730
25926
|
let running = false;
|
|
25731
25927
|
let wakeRequested = false;
|
|
25732
25928
|
let timer;
|
|
@@ -25763,14 +25959,18 @@ function createDurableAutoExtractor(options) {
|
|
|
25763
25959
|
}, delay);
|
|
25764
25960
|
}
|
|
25765
25961
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
25962
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
25766
25963
|
let watchdog;
|
|
25767
25964
|
let cancelled = false;
|
|
25965
|
+
const controller = new AbortController();
|
|
25966
|
+
activeBatch = controller;
|
|
25768
25967
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
25769
25968
|
try {
|
|
25770
25969
|
return await Promise.race([
|
|
25771
25970
|
new Promise((resolve, reject) => {
|
|
25772
25971
|
const worker = createAutoExtractor({
|
|
25773
25972
|
...options,
|
|
25973
|
+
signal: controller.signal,
|
|
25774
25974
|
retainCtx: {
|
|
25775
25975
|
...options.retainCtx,
|
|
25776
25976
|
vaultCtx: {
|
|
@@ -25799,6 +25999,8 @@ function createDurableAutoExtractor(options) {
|
|
|
25799
25999
|
]);
|
|
25800
26000
|
} finally {
|
|
25801
26001
|
cancelled = true;
|
|
26002
|
+
controller.abort();
|
|
26003
|
+
if (activeBatch === controller) activeBatch = null;
|
|
25802
26004
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
25803
26005
|
}
|
|
25804
26006
|
}
|
|
@@ -25810,6 +26012,7 @@ function createDurableAutoExtractor(options) {
|
|
|
25810
26012
|
for (const message of loaded)
|
|
25811
26013
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
25812
26014
|
await database.write(async () => {
|
|
26015
|
+
if (disposed) return;
|
|
25813
26016
|
const current = idsOf(job);
|
|
25814
26017
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
25815
26018
|
if (!acknowledged.length) return;
|
|
@@ -25982,6 +26185,7 @@ function createDurableAutoExtractor(options) {
|
|
|
25982
26185
|
jobScope,
|
|
25983
26186
|
jobFolderId
|
|
25984
26187
|
);
|
|
26188
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
25985
26189
|
options.onTurnComplete?.(result);
|
|
25986
26190
|
return result;
|
|
25987
26191
|
};
|
|
@@ -26018,6 +26222,7 @@ function createDurableAutoExtractor(options) {
|
|
|
26018
26222
|
);
|
|
26019
26223
|
scheduleAfterSuccess = true;
|
|
26020
26224
|
} catch (error) {
|
|
26225
|
+
if (disposed) break;
|
|
26021
26226
|
attempts.set(job.id, attempted + 1);
|
|
26022
26227
|
retry = true;
|
|
26023
26228
|
reportError(error, conversationId);
|
|
@@ -26040,6 +26245,14 @@ function createDurableAutoExtractor(options) {
|
|
|
26040
26245
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
26041
26246
|
}
|
|
26042
26247
|
}
|
|
26248
|
+
function dispose() {
|
|
26249
|
+
disposed = true;
|
|
26250
|
+
activeBatch?.abort(options.signal?.reason);
|
|
26251
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
26252
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
26253
|
+
}
|
|
26254
|
+
if (options.signal?.aborted) dispose();
|
|
26255
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
26043
26256
|
schedule(0);
|
|
26044
26257
|
return {
|
|
26045
26258
|
processTurn(messages, conversationId) {
|
|
@@ -26119,10 +26332,7 @@ function createDurableAutoExtractor(options) {
|
|
|
26119
26332
|
return true;
|
|
26120
26333
|
},
|
|
26121
26334
|
isProcessing: () => running,
|
|
26122
|
-
dispose
|
|
26123
|
-
disposed = true;
|
|
26124
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
26125
|
-
}
|
|
26335
|
+
dispose
|
|
26126
26336
|
};
|
|
26127
26337
|
}
|
|
26128
26338
|
|
|
@@ -32392,6 +32602,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
|
|
|
32392
32602
|
var NO_CONVERSATION_KEY = "__no_conversation__";
|
|
32393
32603
|
var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
|
|
32394
32604
|
var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
|
|
32605
|
+
var MEMORY_STORE_NOT_READY = "Memory store is not ready";
|
|
32395
32606
|
var conversationRedactors = /* @__PURE__ */ new Map();
|
|
32396
32607
|
function getConversationRedactor(conversationId, nerDetector) {
|
|
32397
32608
|
const key = conversationId ?? NO_CONVERSATION_KEY;
|
|
@@ -32482,7 +32693,7 @@ function useChatStorage(options) {
|
|
|
32482
32693
|
() => ({ getToken, baseUrl, model: embeddingModel, maskInput: maskEmbeddingInput }),
|
|
32483
32694
|
[getToken, baseUrl, embeddingModel, maskEmbeddingInput]
|
|
32484
32695
|
);
|
|
32485
|
-
const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
32696
|
+
const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
32486
32697
|
const blobManagerRef = (0, import_react6.useRef)(new BlobUrlManager());
|
|
32487
32698
|
(0, import_react6.useEffect)(() => {
|
|
32488
32699
|
const manager = blobManagerRef.current;
|
|
@@ -32759,6 +32970,7 @@ function useChatStorage(options) {
|
|
|
32759
32970
|
);
|
|
32760
32971
|
const retainVaultMemory = (0, import_react6.useCallback)(
|
|
32761
32972
|
async (input) => {
|
|
32973
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32762
32974
|
if (memoryStore) {
|
|
32763
32975
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
32764
32976
|
if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -32790,6 +33002,7 @@ function useChatStorage(options) {
|
|
|
32790
33002
|
);
|
|
32791
33003
|
const createMemoryVaultTool2 = (0, import_react6.useCallback)(
|
|
32792
33004
|
(options2) => {
|
|
33005
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32793
33006
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
32794
33007
|
const embOpts = getToken ? vaultEmbeddingOptions : void 0;
|
|
32795
33008
|
return createMemoryVaultTool(
|
|
@@ -32811,6 +33024,7 @@ function useChatStorage(options) {
|
|
|
32811
33024
|
);
|
|
32812
33025
|
const getVaultMemories = (0, import_react6.useCallback)(
|
|
32813
33026
|
(options2) => {
|
|
33027
|
+
if (memoryStore === null) return Promise.resolve([]);
|
|
32814
33028
|
if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
|
|
32815
33029
|
const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
|
|
32816
33030
|
if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -32822,6 +33036,7 @@ function useChatStorage(options) {
|
|
|
32822
33036
|
);
|
|
32823
33037
|
const createVaultMemory = (0, import_react6.useCallback)(
|
|
32824
33038
|
async (content, scope) => {
|
|
33039
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32825
33040
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
32826
33041
|
if (memoryStore) return memoryStore.create({ content, scope });
|
|
32827
33042
|
const result = await createVaultMemoryOp(vaultCtx, { content, scope });
|
|
@@ -32843,6 +33058,7 @@ function useChatStorage(options) {
|
|
|
32843
33058
|
);
|
|
32844
33059
|
const updateVaultMemory = (0, import_react6.useCallback)(
|
|
32845
33060
|
async (id, content, scope) => {
|
|
33061
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32846
33062
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
32847
33063
|
if (memoryStore) return memoryStore.update(id, { content, scope });
|
|
32848
33064
|
const existing = await getVaultMemoryOp(vaultCtx, id);
|
|
@@ -32868,6 +33084,7 @@ function useChatStorage(options) {
|
|
|
32868
33084
|
);
|
|
32869
33085
|
const deleteVaultMemory = (0, import_react6.useCallback)(
|
|
32870
33086
|
async (id) => {
|
|
33087
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32871
33088
|
if (memoryStore) return memoryStore.delete(id);
|
|
32872
33089
|
const existing = await getVaultMemoryOp(vaultCtx, id);
|
|
32873
33090
|
const result = await deleteVaultMemoryOp(vaultCtx, id);
|
|
@@ -32881,7 +33098,7 @@ function useChatStorage(options) {
|
|
|
32881
33098
|
const chunkVectorCacheRef = (0, import_react6.useRef)(createChunkVectorCache());
|
|
32882
33099
|
const clientToolEmbeddingsCacheRef = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
|
|
32883
33100
|
(0, import_react6.useEffect)(() => {
|
|
32884
|
-
if (!getToken || memoryStore) return;
|
|
33101
|
+
if (!getToken || memoryStore !== void 0) return;
|
|
32885
33102
|
void (async () => {
|
|
32886
33103
|
try {
|
|
32887
33104
|
await preEmbedVaultMemories(vaultCtx, vaultEmbeddingOptions, vaultEmbeddingCache);
|
|
@@ -32897,6 +33114,7 @@ function useChatStorage(options) {
|
|
|
32897
33114
|
}, [vaultEmbeddingCache]);
|
|
32898
33115
|
const createMemoryVaultSearchTool2 = (0, import_react6.useCallback)(
|
|
32899
33116
|
(searchOptions) => {
|
|
33117
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32900
33118
|
if (!getToken && !memoryStore) {
|
|
32901
33119
|
throw new Error("getToken is required for memory vault search tool");
|
|
32902
33120
|
}
|
|
@@ -32912,6 +33130,7 @@ function useChatStorage(options) {
|
|
|
32912
33130
|
);
|
|
32913
33131
|
const createRecallTool2 = (0, import_react6.useCallback)(
|
|
32914
33132
|
(toolOptions, callbacks) => {
|
|
33133
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
32915
33134
|
if (!getToken && !memoryStore) {
|
|
32916
33135
|
throw new Error("getToken is required for recall tool");
|
|
32917
33136
|
}
|
|
@@ -32951,6 +33170,7 @@ function useChatStorage(options) {
|
|
|
32951
33170
|
);
|
|
32952
33171
|
const searchVaultMemoriesFn = (0, import_react6.useCallback)(
|
|
32953
33172
|
async (query, searchOptions) => {
|
|
33173
|
+
if (memoryStore === null) return [];
|
|
32954
33174
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
32955
33175
|
if (memoryStore) return (await memoryStore.factSource.search(query, searchOptions)).results;
|
|
32956
33176
|
if (!getToken) return [];
|
|
@@ -32966,7 +33186,7 @@ function useChatStorage(options) {
|
|
|
32966
33186
|
);
|
|
32967
33187
|
const recallFn = (0, import_react6.useCallback)(
|
|
32968
33188
|
async (query, options2) => {
|
|
32969
|
-
if (!getToken && !memoryStore) {
|
|
33189
|
+
if (memoryStore === null || !getToken && !memoryStore) {
|
|
32970
33190
|
return {
|
|
32971
33191
|
memories: [],
|
|
32972
33192
|
usedBudget: options2?.budget ?? "low",
|