@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/expo/index.cjs
CHANGED
|
@@ -3731,8 +3731,9 @@ async function updateConversationPinnedOp(ctx, id, pinned) {
|
|
|
3731
3731
|
}
|
|
3732
3732
|
return false;
|
|
3733
3733
|
}
|
|
3734
|
-
async function getMessagesOp(ctx, convId) {
|
|
3735
|
-
const
|
|
3734
|
+
async function getMessagesOp(ctx, convId, opts) {
|
|
3735
|
+
const fetched = await ctx.messagesCollection.query(import_watermelondb2.Q.where("conversation_id", convId), import_watermelondb2.Q.sortBy("message_id", import_watermelondb2.Q.asc)).unsafeFetchRaw();
|
|
3736
|
+
const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
|
|
3736
3737
|
return Promise.all(
|
|
3737
3738
|
results.map(
|
|
3738
3739
|
(raw) => messageRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
@@ -5885,6 +5886,37 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
|
|
|
5885
5886
|
}));
|
|
5886
5887
|
return updateMessageChunksOp(ctx, messageId, messageChunks, embeddingModel);
|
|
5887
5888
|
}
|
|
5889
|
+
var MIN_SEALED_EMBEDDING_HEX = 256;
|
|
5890
|
+
function rawHasEmbedding(value) {
|
|
5891
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
5892
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
5893
|
+
if (isEncrypted(value)) {
|
|
5894
|
+
return value.length - value.indexOf(":", 4) - 1 >= MIN_SEALED_EMBEDDING_HEX;
|
|
5895
|
+
}
|
|
5896
|
+
try {
|
|
5897
|
+
const parsed = JSON.parse(value);
|
|
5898
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
5899
|
+
} catch {
|
|
5900
|
+
return false;
|
|
5901
|
+
}
|
|
5902
|
+
}
|
|
5903
|
+
function sealedVersion(value) {
|
|
5904
|
+
if (typeof value !== "string" || !isEncrypted(value)) return null;
|
|
5905
|
+
return value.startsWith("enc:v2:") ? "v2" : "v3";
|
|
5906
|
+
}
|
|
5907
|
+
function mayNeedChunkEmbedding(raw, embeddingModel, filter) {
|
|
5908
|
+
const role = raw.role;
|
|
5909
|
+
if (role === "system") return false;
|
|
5910
|
+
if (filter?.roles && !filter.roles.includes(role ?? "")) return false;
|
|
5911
|
+
if (isNonEmbeddableOrigin(raw.origin, filter?.reembedDiscarded)) {
|
|
5912
|
+
return false;
|
|
5913
|
+
}
|
|
5914
|
+
const model = raw.embedding_model;
|
|
5915
|
+
if (typeof model === "string" && model !== embeddingModel) return true;
|
|
5916
|
+
if (rawHasEmbedding(raw.chunks)) return false;
|
|
5917
|
+
if (rawHasEmbedding(raw.vector) && !filter?.rechunkExisting) return false;
|
|
5918
|
+
return true;
|
|
5919
|
+
}
|
|
5888
5920
|
async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
5889
5921
|
const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5890
5922
|
const { chunkSize = DEFAULT_CHUNK_SIZE } = options;
|
|
@@ -5897,11 +5929,31 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
5897
5929
|
let considered = 0;
|
|
5898
5930
|
let sealedRowsSeen = 0;
|
|
5899
5931
|
let rowsSeen = 0;
|
|
5932
|
+
const keptSealed = /* @__PURE__ */ new Map();
|
|
5933
|
+
const candidatesStillSealed = /* @__PURE__ */ new Map();
|
|
5934
|
+
const droppedSealed = /* @__PURE__ */ new Map();
|
|
5935
|
+
const rawFilter = (raw) => {
|
|
5936
|
+
rowsSeen++;
|
|
5937
|
+
const keep = mayNeedChunkEmbedding(raw, embeddingModel, filter);
|
|
5938
|
+
const version = sealedVersion(raw.content);
|
|
5939
|
+
if (!version) return keep;
|
|
5940
|
+
if (keep) {
|
|
5941
|
+
keptSealed.set(version, (keptSealed.get(version) ?? 0) + 1);
|
|
5942
|
+
} else {
|
|
5943
|
+
const dropped = droppedSealed.get(version);
|
|
5944
|
+
if (dropped) dropped.count++;
|
|
5945
|
+
else droppedSealed.set(version, { count: 1, probeId: raw.id });
|
|
5946
|
+
}
|
|
5947
|
+
return keep;
|
|
5948
|
+
};
|
|
5900
5949
|
for (const conv of targetConversations) {
|
|
5901
|
-
const messages = await getMessagesOp(ctx, conv.conversationId);
|
|
5950
|
+
const messages = await getMessagesOp(ctx, conv.conversationId, { rawFilter });
|
|
5902
5951
|
for (const message of messages) {
|
|
5903
|
-
|
|
5904
|
-
if (
|
|
5952
|
+
const stillSealed = sealedVersion(message.content);
|
|
5953
|
+
if (stillSealed) {
|
|
5954
|
+
sealedRowsSeen++;
|
|
5955
|
+
candidatesStillSealed.set(stillSealed, (candidatesStillSealed.get(stillSealed) ?? 0) + 1);
|
|
5956
|
+
}
|
|
5905
5957
|
const isStale = message.embeddingModel !== void 0 && message.embeddingModel !== null && message.embeddingModel !== embeddingModel;
|
|
5906
5958
|
if (message.chunks && message.chunks.length > 0 && !isStale) continue;
|
|
5907
5959
|
const hasVector = message.vector && message.vector.length > 0;
|
|
@@ -5914,6 +5966,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
5914
5966
|
stillEncrypted++;
|
|
5915
5967
|
continue;
|
|
5916
5968
|
}
|
|
5969
|
+
if (isToolResultsRow(message)) continue;
|
|
5917
5970
|
if (message.content.length < minLength) continue;
|
|
5918
5971
|
if (shouldChunkMessage(message.content, chunkSize)) {
|
|
5919
5972
|
longMessages.push({
|
|
@@ -5925,6 +5978,12 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
5925
5978
|
}
|
|
5926
5979
|
}
|
|
5927
5980
|
}
|
|
5981
|
+
for (const [version, dropped] of droppedSealed) {
|
|
5982
|
+
const keyOpenedACandidate = (keptSealed.get(version) ?? 0) > (candidatesStillSealed.get(version) ?? 0);
|
|
5983
|
+
if (keyOpenedACandidate) continue;
|
|
5984
|
+
const probe = await getMessageOp(ctx, dropped.probeId);
|
|
5985
|
+
if (!probe || isEncrypted(probe.content)) sealedRowsSeen += dropped.count;
|
|
5986
|
+
}
|
|
5928
5987
|
if (stillEncrypted > 0 || sealedRowsSeen > 0) {
|
|
5929
5988
|
getLogger().error(
|
|
5930
5989
|
"memoryEngine: messages still encrypted (key unavailable?) \u2014 excluded from embedding",
|
|
@@ -12639,6 +12698,11 @@ init_logger();
|
|
|
12639
12698
|
|
|
12640
12699
|
// src/lib/db/entities/operations.ts
|
|
12641
12700
|
var import_watermelondb19 = require("@nozbe/watermelondb");
|
|
12701
|
+
async function assertCanWrite(ctx) {
|
|
12702
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
12703
|
+
throw new Error("Memory source is no longer eligible");
|
|
12704
|
+
}
|
|
12705
|
+
}
|
|
12642
12706
|
function entityToStored(e) {
|
|
12643
12707
|
return {
|
|
12644
12708
|
uniqueId: e.id,
|
|
@@ -12779,6 +12843,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
12779
12843
|
let skipped = false;
|
|
12780
12844
|
let entities = [];
|
|
12781
12845
|
await ctx.database.write(async () => {
|
|
12846
|
+
await assertCanWrite(ctx);
|
|
12782
12847
|
const {
|
|
12783
12848
|
entities: byName,
|
|
12784
12849
|
operations: entityOps,
|
|
@@ -12854,6 +12919,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
12854
12919
|
let skipped = false;
|
|
12855
12920
|
let entities = [];
|
|
12856
12921
|
await ctx.database.write(async () => {
|
|
12922
|
+
await assertCanWrite(ctx);
|
|
12857
12923
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
12858
12924
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
12859
12925
|
skipped = true;
|
|
@@ -12914,6 +12980,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
12914
12980
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("memory_id", import_watermelondb19.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
12915
12981
|
if (links.length === 0) return;
|
|
12916
12982
|
await ctx.database.write(async () => {
|
|
12983
|
+
await assertCanWrite(ctx);
|
|
12917
12984
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
12918
12985
|
});
|
|
12919
12986
|
}
|
|
@@ -12922,6 +12989,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
12922
12989
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("user_id", userId)).fetch();
|
|
12923
12990
|
if (links.length === 0) return;
|
|
12924
12991
|
await ctx.database.write(async () => {
|
|
12992
|
+
await assertCanWrite(ctx);
|
|
12925
12993
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
12926
12994
|
});
|
|
12927
12995
|
}
|
|
@@ -13086,6 +13154,11 @@ function visibilityConditions(requested) {
|
|
|
13086
13154
|
function isKinded(record2) {
|
|
13087
13155
|
return record2.kind !== null && record2.kind !== void 0;
|
|
13088
13156
|
}
|
|
13157
|
+
async function assertCanWrite2(ctx) {
|
|
13158
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
13159
|
+
throw new Error("Memory source is no longer eligible");
|
|
13160
|
+
}
|
|
13161
|
+
}
|
|
13089
13162
|
function assertValidKindLevel(kind, level) {
|
|
13090
13163
|
const hasKind = kind !== null && kind !== void 0;
|
|
13091
13164
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -13266,8 +13339,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
13266
13339
|
ctx.embeddedWalletSigner
|
|
13267
13340
|
) : opts.content;
|
|
13268
13341
|
const created = await ctx.database.write(async () => {
|
|
13269
|
-
|
|
13270
|
-
throw new Error("Memory source is no longer eligible");
|
|
13342
|
+
await assertCanWrite2(ctx);
|
|
13271
13343
|
return ctx.vaultMemoryCollection.create(
|
|
13272
13344
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13273
13345
|
);
|
|
@@ -13286,8 +13358,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
13286
13358
|
) : opts.content;
|
|
13287
13359
|
let createdRecord = null;
|
|
13288
13360
|
await ctx.database.write(async () => {
|
|
13289
|
-
|
|
13290
|
-
throw new Error("Memory source is no longer eligible");
|
|
13361
|
+
await assertCanWrite2(ctx);
|
|
13291
13362
|
let target;
|
|
13292
13363
|
try {
|
|
13293
13364
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -13379,8 +13450,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13379
13450
|
})
|
|
13380
13451
|
);
|
|
13381
13452
|
const created = await ctx.database.write(async () => {
|
|
13382
|
-
|
|
13383
|
-
throw new Error("Memory source is no longer eligible");
|
|
13453
|
+
await assertCanWrite2(ctx);
|
|
13384
13454
|
const prepared = optionsArray.map(
|
|
13385
13455
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
13386
13456
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -13685,8 +13755,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13685
13755
|
const record2 = probe;
|
|
13686
13756
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13687
13757
|
await ctx.database.write(async () => {
|
|
13688
|
-
|
|
13689
|
-
throw new Error("Memory source is no longer eligible");
|
|
13758
|
+
await assertCanWrite2(ctx);
|
|
13690
13759
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
13691
13760
|
stale = true;
|
|
13692
13761
|
return;
|
|
@@ -13797,6 +13866,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
13797
13866
|
let stale = false;
|
|
13798
13867
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13799
13868
|
await ctx.database.write(async (writer) => {
|
|
13869
|
+
await assertCanWrite2(ctx);
|
|
13800
13870
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13801
13871
|
stale = true;
|
|
13802
13872
|
return;
|
|
@@ -13838,6 +13908,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
13838
13908
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13839
13909
|
let cleared = false;
|
|
13840
13910
|
await ctx.database.write(async () => {
|
|
13911
|
+
await assertCanWrite2(ctx);
|
|
13841
13912
|
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
13842
13913
|
cleared = true;
|
|
13843
13914
|
await record2.update((r) => {
|
|
@@ -13861,6 +13932,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
13861
13932
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
13862
13933
|
let stale = false;
|
|
13863
13934
|
await ctx.database.write(async () => {
|
|
13935
|
+
await assertCanWrite2(ctx);
|
|
13864
13936
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13865
13937
|
stale = true;
|
|
13866
13938
|
return;
|
|
@@ -13889,6 +13961,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
13889
13961
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
13890
13962
|
let stale = false;
|
|
13891
13963
|
await ctx.database.write(async () => {
|
|
13964
|
+
await assertCanWrite2(ctx);
|
|
13892
13965
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13893
13966
|
stale = true;
|
|
13894
13967
|
return;
|
|
@@ -13926,8 +13999,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
13926
13999
|
}
|
|
13927
14000
|
let stale = false;
|
|
13928
14001
|
await ctx.database.write(async () => {
|
|
13929
|
-
|
|
13930
|
-
throw new Error("Memory source is no longer eligible");
|
|
14002
|
+
await assertCanWrite2(ctx);
|
|
13931
14003
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
13932
14004
|
stale = true;
|
|
13933
14005
|
return;
|
|
@@ -14089,6 +14161,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
14089
14161
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
14090
14162
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
14091
14163
|
await ctx.database.write(async () => {
|
|
14164
|
+
await assertCanWrite2(ctx);
|
|
14092
14165
|
const records = [];
|
|
14093
14166
|
for (const id of chunkIds) {
|
|
14094
14167
|
try {
|
|
@@ -14122,6 +14195,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14122
14195
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
14123
14196
|
try {
|
|
14124
14197
|
await ctx.database.write(async (writer) => {
|
|
14198
|
+
await assertCanWrite2(ctx);
|
|
14125
14199
|
let record2;
|
|
14126
14200
|
try {
|
|
14127
14201
|
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -14152,6 +14226,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14152
14226
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
14153
14227
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
14154
14228
|
await ctx.database.write(async () => {
|
|
14229
|
+
await assertCanWrite2(ctx);
|
|
14155
14230
|
const writes = [];
|
|
14156
14231
|
for (const id of chunkIds) {
|
|
14157
14232
|
let record2;
|
|
@@ -14184,6 +14259,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
14184
14259
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb20.Q.where("user_id", userId), import_watermelondb20.Q.where("is_deleted", false)).fetch();
|
|
14185
14260
|
if (records.length === 0) return 0;
|
|
14186
14261
|
await ctx.database.write(async () => {
|
|
14262
|
+
await assertCanWrite2(ctx);
|
|
14187
14263
|
const prepared = records.map(
|
|
14188
14264
|
(record2) => record2.prepareUpdate((r) => {
|
|
14189
14265
|
r._setRaw("is_deleted", true);
|
|
@@ -14238,6 +14314,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
14238
14314
|
let stale = false;
|
|
14239
14315
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
14240
14316
|
await ctx.database.write(async () => {
|
|
14317
|
+
await assertCanWrite2(ctx);
|
|
14241
14318
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
14242
14319
|
stale = true;
|
|
14243
14320
|
return;
|
|
@@ -14261,6 +14338,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
14261
14338
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14262
14339
|
let stale = false;
|
|
14263
14340
|
await ctx.database.write(async () => {
|
|
14341
|
+
await assertCanWrite2(ctx);
|
|
14264
14342
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14265
14343
|
stale = true;
|
|
14266
14344
|
return;
|
|
@@ -14281,6 +14359,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
14281
14359
|
const now = opts.now ?? Date.now();
|
|
14282
14360
|
let stale = false;
|
|
14283
14361
|
await ctx.database.write(async () => {
|
|
14362
|
+
await assertCanWrite2(ctx);
|
|
14284
14363
|
const archivedAt = record2.archivedAt;
|
|
14285
14364
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
14286
14365
|
stale = true;
|
|
@@ -14320,6 +14399,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
|
|
|
14320
14399
|
}
|
|
14321
14400
|
let written = false;
|
|
14322
14401
|
await ctx.database.write(async () => {
|
|
14402
|
+
await assertCanWrite2(ctx);
|
|
14323
14403
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14324
14404
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14325
14405
|
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
@@ -17856,6 +17936,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
17856
17936
|
).map((c) => c.candidate);
|
|
17857
17937
|
}
|
|
17858
17938
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
17939
|
+
const { memoryStore, signal } = options;
|
|
17940
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
17941
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
17942
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
17943
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
17944
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
17945
|
+
signal?.throwIfAborted();
|
|
17859
17946
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
17860
17947
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
17861
17948
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -17889,6 +17976,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17889
17976
|
}
|
|
17890
17977
|
});
|
|
17891
17978
|
const extractMs = Date.now() - tExtract;
|
|
17979
|
+
signal?.throwIfAborted();
|
|
17892
17980
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
17893
17981
|
const log = getLogger();
|
|
17894
17982
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -17936,16 +18024,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17936
18024
|
const results = [];
|
|
17937
18025
|
const quarantinedInfo = [];
|
|
17938
18026
|
let failedWrites = 0;
|
|
18027
|
+
let auditRows;
|
|
17939
18028
|
const tRetain = Date.now();
|
|
17940
18029
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
17941
18030
|
try {
|
|
18031
|
+
signal?.throwIfAborted();
|
|
17942
18032
|
if (isQuarantined) {
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
18033
|
+
let existingId;
|
|
18034
|
+
if (memoryStore) {
|
|
18035
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
18036
|
+
scopes: [options.scope ?? "private"],
|
|
18037
|
+
includeArchived: true,
|
|
18038
|
+
includeQuarantined: true,
|
|
18039
|
+
includeSuperseded: true
|
|
18040
|
+
}));
|
|
18041
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
18042
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
18043
|
+
existingId = (await auditRows).find(
|
|
18044
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
18045
|
+
)?.uniqueId ?? null;
|
|
18046
|
+
} else {
|
|
18047
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
18048
|
+
retainCtx.vaultCtx,
|
|
18049
|
+
candidate.content,
|
|
18050
|
+
candidate.sourceMessageIds,
|
|
18051
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
18052
|
+
).catch(() => null);
|
|
18053
|
+
}
|
|
17949
18054
|
if (existingId) {
|
|
17950
18055
|
quarantinedInfo.push({
|
|
17951
18056
|
candidate,
|
|
@@ -17956,18 +18061,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17956
18061
|
continue;
|
|
17957
18062
|
}
|
|
17958
18063
|
}
|
|
17959
|
-
const
|
|
18064
|
+
const retainOptions = {
|
|
17960
18065
|
source: "auto-extracted",
|
|
17961
18066
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
17962
18067
|
respectTombstones: true,
|
|
17963
18068
|
...options.scope !== void 0 && { scope: options.scope },
|
|
17964
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
17965
18069
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
17966
18070
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
17967
18071
|
factType: candidate.type,
|
|
17968
18072
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
18073
|
+
};
|
|
18074
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
18075
|
+
...retainOptions,
|
|
18076
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
18077
|
+
signal
|
|
18078
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
18079
|
+
...retainOptions,
|
|
18080
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
17969
18081
|
});
|
|
17970
18082
|
if (isQuarantined) {
|
|
18083
|
+
auditRows = void 0;
|
|
17971
18084
|
const info = {
|
|
17972
18085
|
candidate,
|
|
17973
18086
|
memoryId: result.memoryId,
|
|
@@ -17986,9 +18099,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17986
18099
|
}
|
|
17987
18100
|
succeededCandidates.push(candidate);
|
|
17988
18101
|
results.push(result);
|
|
17989
|
-
if (result.action !== "suppressed" &&
|
|
18102
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
17990
18103
|
try {
|
|
17991
|
-
|
|
18104
|
+
signal?.throwIfAborted();
|
|
18105
|
+
if (memoryStore) {
|
|
18106
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
18107
|
+
unlessUserManaged: true,
|
|
18108
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
18109
|
+
signal
|
|
18110
|
+
});
|
|
18111
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
17992
18112
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
17993
18113
|
unlessTopicsUserManaged: true
|
|
17994
18114
|
});
|
|
@@ -18238,7 +18358,7 @@ function createAutoExtractor(options) {
|
|
|
18238
18358
|
};
|
|
18239
18359
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
18240
18360
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
18241
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
18361
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
18242
18362
|
getLogger().warn(
|
|
18243
18363
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
18244
18364
|
);
|
|
@@ -18283,6 +18403,8 @@ function createAutoExtractor(options) {
|
|
|
18283
18403
|
try {
|
|
18284
18404
|
const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
18285
18405
|
extract,
|
|
18406
|
+
memoryStore: options.memoryStore,
|
|
18407
|
+
signal: options.signal,
|
|
18286
18408
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
18287
18409
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
18288
18410
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -20384,6 +20506,7 @@ function createLocalMemoryStore(options) {
|
|
|
20384
20506
|
database,
|
|
20385
20507
|
entityCollection: database.get("entity"),
|
|
20386
20508
|
memoryEntityCollection: database.get("memory_entity"),
|
|
20509
|
+
canWrite: options.canWrite,
|
|
20387
20510
|
...userId !== void 0 && { userId },
|
|
20388
20511
|
...options.allowUnscopedRows !== void 0 && {
|
|
20389
20512
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -20395,10 +20518,21 @@ function createLocalMemoryStore(options) {
|
|
|
20395
20518
|
walletAddress: options.walletAddress,
|
|
20396
20519
|
signMessage: options.signMessage,
|
|
20397
20520
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
20521
|
+
canWrite: options.canWrite,
|
|
20398
20522
|
...userId !== void 0 && { userId },
|
|
20399
20523
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
20400
20524
|
entityCtx
|
|
20401
20525
|
};
|
|
20526
|
+
const assertWrite = async (writeOptions) => {
|
|
20527
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20528
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
20529
|
+
throw new Error("Memory source is no longer eligible");
|
|
20530
|
+
}
|
|
20531
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
20532
|
+
throw new Error("Memory source is no longer eligible");
|
|
20533
|
+
}
|
|
20534
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20535
|
+
};
|
|
20402
20536
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
20403
20537
|
const ownedBy = userId !== void 0 ? [import_watermelondb23.Q.where("user_id", userId)] : [];
|
|
20404
20538
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb23.Q.or(import_watermelondb23.Q.where("user_id", userId), import_watermelondb23.Q.where("user_id", null))] : [import_watermelondb23.Q.where("user_id", userId)];
|
|
@@ -20510,9 +20644,25 @@ function createLocalMemoryStore(options) {
|
|
|
20510
20644
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
20511
20645
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
20512
20646
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
20513
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
20647
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
20648
|
+
await assertWrite(writeOptions);
|
|
20514
20649
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb23.Q.where("id", memoryId), import_watermelondb23.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
20515
|
-
return owned > 0 ? writer.callWriter(
|
|
20650
|
+
return owned > 0 ? writer.callWriter(
|
|
20651
|
+
() => linkMemoryEntitiesOp(
|
|
20652
|
+
{
|
|
20653
|
+
...entityCtx,
|
|
20654
|
+
canWrite: async () => {
|
|
20655
|
+
await assertWrite(writeOptions);
|
|
20656
|
+
return true;
|
|
20657
|
+
}
|
|
20658
|
+
},
|
|
20659
|
+
memoryId,
|
|
20660
|
+
topics,
|
|
20661
|
+
{
|
|
20662
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
20663
|
+
}
|
|
20664
|
+
)
|
|
20665
|
+
) : [];
|
|
20516
20666
|
}),
|
|
20517
20667
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
20518
20668
|
recall: (query, recallOptions) => recall(
|
|
@@ -20522,7 +20672,17 @@ function createLocalMemoryStore(options) {
|
|
|
20522
20672
|
),
|
|
20523
20673
|
retain: (content, retainOptions) => retain(
|
|
20524
20674
|
content,
|
|
20525
|
-
{
|
|
20675
|
+
{
|
|
20676
|
+
vaultCtx: {
|
|
20677
|
+
...vaultCtx,
|
|
20678
|
+
canWrite: async () => {
|
|
20679
|
+
await assertWrite(retainOptions);
|
|
20680
|
+
return true;
|
|
20681
|
+
}
|
|
20682
|
+
},
|
|
20683
|
+
embeddingOptions: options.embeddingOptions,
|
|
20684
|
+
vaultCache
|
|
20685
|
+
},
|
|
20526
20686
|
retainOptions
|
|
20527
20687
|
),
|
|
20528
20688
|
factSource: {
|
|
@@ -21161,7 +21321,14 @@ function stored(row) {
|
|
|
21161
21321
|
function createRemoteMemoryPipeline(options) {
|
|
21162
21322
|
const { persistence, embeddingOptions } = options;
|
|
21163
21323
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21164
|
-
const operation = (mode) => {
|
|
21324
|
+
const operation = (mode, writeOptions) => {
|
|
21325
|
+
const signal = writeOptions?.signal;
|
|
21326
|
+
const assertWrite = async () => {
|
|
21327
|
+
signal?.throwIfAborted();
|
|
21328
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
21329
|
+
throw new Error("Memory source is no longer eligible");
|
|
21330
|
+
signal?.throwIfAborted();
|
|
21331
|
+
};
|
|
21165
21332
|
const rejectUndecryptable = (failed) => {
|
|
21166
21333
|
if (!failed.length) return;
|
|
21167
21334
|
if (mode === "retain")
|
|
@@ -21179,7 +21346,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21179
21346
|
return items.map((item) => stored(item.memory));
|
|
21180
21347
|
};
|
|
21181
21348
|
const get = async (id) => {
|
|
21182
|
-
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
21349
|
+
const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
21183
21350
|
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
21184
21351
|
snapshots.set(id, snapshot);
|
|
21185
21352
|
return stored(snapshot.memory);
|
|
@@ -21225,7 +21392,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21225
21392
|
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
21226
21393
|
}
|
|
21227
21394
|
const forceIds = [...forced];
|
|
21228
|
-
const windowOptions = (i,
|
|
21395
|
+
const windowOptions = (i, signal2) => ({
|
|
21229
21396
|
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
21230
21397
|
force_ids: i === 0 ? forceIds : [],
|
|
21231
21398
|
...search.scopes && { scopes: search.scopes },
|
|
@@ -21233,13 +21400,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21233
21400
|
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
21234
21401
|
include_archived: search.includeArchived,
|
|
21235
21402
|
embedding_model: model,
|
|
21236
|
-
...
|
|
21403
|
+
...signal2 && { signal: signal2 }
|
|
21237
21404
|
});
|
|
21238
21405
|
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
21239
21406
|
let windows;
|
|
21240
21407
|
if (mode === "retain") {
|
|
21241
21408
|
windows = await Promise.all(
|
|
21242
|
-
vectors.map(
|
|
21409
|
+
vectors.map(
|
|
21410
|
+
(embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
|
|
21411
|
+
)
|
|
21243
21412
|
);
|
|
21244
21413
|
} else {
|
|
21245
21414
|
const deadline = new AbortController();
|
|
@@ -21327,12 +21496,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21327
21496
|
twin_opt_in: false
|
|
21328
21497
|
};
|
|
21329
21498
|
};
|
|
21330
|
-
const write = async (memory, snapshot) =>
|
|
21499
|
+
const write = async (memory, snapshot) => {
|
|
21500
|
+
await assertWrite();
|
|
21501
|
+
return remember([await persistence.put(memory, snapshot, signal)])[0];
|
|
21502
|
+
};
|
|
21331
21503
|
const port = {
|
|
21332
21504
|
prepare,
|
|
21333
21505
|
get,
|
|
21334
21506
|
getFresh: async (id) => {
|
|
21335
|
-
const current = await persistence.get(id);
|
|
21507
|
+
const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
21336
21508
|
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
21337
21509
|
},
|
|
21338
21510
|
tombstones: async (embedding2, embeddingModel, scope, folderId) => {
|
|
@@ -21343,7 +21515,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21343
21515
|
embedding_model: embeddingModel,
|
|
21344
21516
|
strict_model: true,
|
|
21345
21517
|
include_deleted: true,
|
|
21346
|
-
deleted_only: true
|
|
21518
|
+
deleted_only: true,
|
|
21519
|
+
signal
|
|
21347
21520
|
});
|
|
21348
21521
|
rejectUndecryptable(window2.failed);
|
|
21349
21522
|
return remember(window2.items);
|
|
@@ -21399,14 +21572,18 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21399
21572
|
if (!target || !newer || id === successor) return false;
|
|
21400
21573
|
const old = snapshots.get(id);
|
|
21401
21574
|
const next = snapshots.get(successor);
|
|
21575
|
+
await assertWrite();
|
|
21402
21576
|
remember(
|
|
21403
|
-
await persistence.putMany(
|
|
21404
|
-
|
|
21405
|
-
|
|
21406
|
-
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21577
|
+
await persistence.putMany(
|
|
21578
|
+
[
|
|
21579
|
+
{
|
|
21580
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
21581
|
+
expectedVersion: old
|
|
21582
|
+
},
|
|
21583
|
+
{ memory: next.memory, expectedVersion: next }
|
|
21584
|
+
],
|
|
21585
|
+
signal
|
|
21586
|
+
)
|
|
21410
21587
|
);
|
|
21411
21588
|
return true;
|
|
21412
21589
|
},
|
|
@@ -21415,18 +21592,22 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21415
21592
|
if (!target) return { created: null, retired: false };
|
|
21416
21593
|
const snapshot = snapshots.get(targetId);
|
|
21417
21594
|
const successor = createRow(input);
|
|
21595
|
+
await assertWrite();
|
|
21418
21596
|
const rows = remember(
|
|
21419
|
-
await persistence.putMany(
|
|
21420
|
-
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
|
|
21428
|
-
|
|
21429
|
-
|
|
21597
|
+
await persistence.putMany(
|
|
21598
|
+
[
|
|
21599
|
+
{ memory: successor, expectedVersion: 0 },
|
|
21600
|
+
{
|
|
21601
|
+
memory: {
|
|
21602
|
+
...snapshot.memory,
|
|
21603
|
+
superseded_by: successor.memory_id,
|
|
21604
|
+
superseded_at: Date.now()
|
|
21605
|
+
},
|
|
21606
|
+
expectedVersion: snapshot
|
|
21607
|
+
}
|
|
21608
|
+
],
|
|
21609
|
+
signal
|
|
21610
|
+
)
|
|
21430
21611
|
);
|
|
21431
21612
|
return { created: rows[0], retired: true };
|
|
21432
21613
|
}
|
|
@@ -21459,7 +21640,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21459
21640
|
factSource,
|
|
21460
21641
|
recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
|
|
21461
21642
|
retain: async (content, retainOptions) => {
|
|
21462
|
-
const { port } = operation("retain");
|
|
21643
|
+
const { port } = operation("retain", retainOptions);
|
|
21463
21644
|
return retainWithPersistence(
|
|
21464
21645
|
content,
|
|
21465
21646
|
{
|
|
@@ -22042,16 +22223,21 @@ function createRemoteMemoryStore(options) {
|
|
|
22042
22223
|
const record2 = await persistence.get(id);
|
|
22043
22224
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
22044
22225
|
};
|
|
22045
|
-
const mutateLocked = async (id, change, edit) => {
|
|
22046
|
-
|
|
22226
|
+
const mutateLocked = async (id, change, edit, writeOptions) => {
|
|
22227
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22228
|
+
const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
|
|
22047
22229
|
if (!record2) return null;
|
|
22230
|
+
if (record2.memory.is_deleted) return null;
|
|
22231
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
22232
|
+
throw new Error("Memory source is no longer eligible");
|
|
22233
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22048
22234
|
const next = edit(structuredClone(record2.memory));
|
|
22049
22235
|
if (!next) return null;
|
|
22050
|
-
const saved = await persistence.put(next, record2);
|
|
22236
|
+
const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
|
|
22051
22237
|
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
22052
22238
|
return saved;
|
|
22053
22239
|
};
|
|
22054
|
-
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
22240
|
+
const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
|
|
22055
22241
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
22056
22242
|
const mutateMany = async (ids, change, edit) => {
|
|
22057
22243
|
const saved = /* @__PURE__ */ new Map();
|
|
@@ -22564,13 +22750,21 @@ function createRemoteMemoryStore(options) {
|
|
|
22564
22750
|
}))
|
|
22565
22751
|
);
|
|
22566
22752
|
},
|
|
22567
|
-
addTopics: async (memoryId, topics) => {
|
|
22753
|
+
addTopics: async (memoryId, topics, writeOptions) => {
|
|
22568
22754
|
const added = await withKnownKinds(topicInputs(topics, "auto"));
|
|
22569
|
-
const saved = await mutate(
|
|
22570
|
-
|
|
22571
|
-
|
|
22572
|
-
|
|
22573
|
-
|
|
22755
|
+
const saved = await mutate(
|
|
22756
|
+
memoryId,
|
|
22757
|
+
"edit",
|
|
22758
|
+
(memory) => {
|
|
22759
|
+
if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
|
|
22760
|
+
return {
|
|
22761
|
+
...memory,
|
|
22762
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
22763
|
+
topics_updated_at: Date.now()
|
|
22764
|
+
};
|
|
22765
|
+
},
|
|
22766
|
+
writeOptions
|
|
22767
|
+
);
|
|
22574
22768
|
if (!saved) return [];
|
|
22575
22769
|
const now = /* @__PURE__ */ new Date();
|
|
22576
22770
|
return mergeTopics([], added).map(
|
|
@@ -23423,6 +23617,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23423
23617
|
};
|
|
23424
23618
|
const folderId = options.folderId ?? null;
|
|
23425
23619
|
let disposed = false;
|
|
23620
|
+
let activeBatch = null;
|
|
23426
23621
|
let running = false;
|
|
23427
23622
|
let wakeRequested = false;
|
|
23428
23623
|
let timer;
|
|
@@ -23459,14 +23654,18 @@ function createDurableAutoExtractor(options) {
|
|
|
23459
23654
|
}, delay);
|
|
23460
23655
|
}
|
|
23461
23656
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
23657
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
23462
23658
|
let watchdog;
|
|
23463
23659
|
let cancelled = false;
|
|
23660
|
+
const controller = new AbortController();
|
|
23661
|
+
activeBatch = controller;
|
|
23464
23662
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
23465
23663
|
try {
|
|
23466
23664
|
return await Promise.race([
|
|
23467
23665
|
new Promise((resolve, reject) => {
|
|
23468
23666
|
const worker = createAutoExtractor({
|
|
23469
23667
|
...options,
|
|
23668
|
+
signal: controller.signal,
|
|
23470
23669
|
retainCtx: {
|
|
23471
23670
|
...options.retainCtx,
|
|
23472
23671
|
vaultCtx: {
|
|
@@ -23495,6 +23694,8 @@ function createDurableAutoExtractor(options) {
|
|
|
23495
23694
|
]);
|
|
23496
23695
|
} finally {
|
|
23497
23696
|
cancelled = true;
|
|
23697
|
+
controller.abort();
|
|
23698
|
+
if (activeBatch === controller) activeBatch = null;
|
|
23498
23699
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
23499
23700
|
}
|
|
23500
23701
|
}
|
|
@@ -23506,6 +23707,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23506
23707
|
for (const message of loaded)
|
|
23507
23708
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
23508
23709
|
await database.write(async () => {
|
|
23710
|
+
if (disposed) return;
|
|
23509
23711
|
const current = idsOf(job);
|
|
23510
23712
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
23511
23713
|
if (!acknowledged.length) return;
|
|
@@ -23678,6 +23880,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23678
23880
|
jobScope,
|
|
23679
23881
|
jobFolderId
|
|
23680
23882
|
);
|
|
23883
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
23681
23884
|
options.onTurnComplete?.(result);
|
|
23682
23885
|
return result;
|
|
23683
23886
|
};
|
|
@@ -23714,6 +23917,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23714
23917
|
);
|
|
23715
23918
|
scheduleAfterSuccess = true;
|
|
23716
23919
|
} catch (error) {
|
|
23920
|
+
if (disposed) break;
|
|
23717
23921
|
attempts.set(job.id, attempted + 1);
|
|
23718
23922
|
retry = true;
|
|
23719
23923
|
reportError(error, conversationId);
|
|
@@ -23736,6 +23940,14 @@ function createDurableAutoExtractor(options) {
|
|
|
23736
23940
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
23737
23941
|
}
|
|
23738
23942
|
}
|
|
23943
|
+
function dispose() {
|
|
23944
|
+
disposed = true;
|
|
23945
|
+
activeBatch?.abort(options.signal?.reason);
|
|
23946
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
23947
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
23948
|
+
}
|
|
23949
|
+
if (options.signal?.aborted) dispose();
|
|
23950
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
23739
23951
|
schedule(0);
|
|
23740
23952
|
return {
|
|
23741
23953
|
processTurn(messages, conversationId) {
|
|
@@ -23815,10 +24027,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23815
24027
|
return true;
|
|
23816
24028
|
},
|
|
23817
24029
|
isProcessing: () => running,
|
|
23818
|
-
dispose
|
|
23819
|
-
disposed = true;
|
|
23820
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
23821
|
-
}
|
|
24030
|
+
dispose
|
|
23822
24031
|
};
|
|
23823
24032
|
}
|
|
23824
24033
|
|
|
@@ -27090,6 +27299,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
|
|
|
27090
27299
|
var NO_CONVERSATION_KEY = "__no_conversation__";
|
|
27091
27300
|
var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
|
|
27092
27301
|
var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
|
|
27302
|
+
var MEMORY_STORE_NOT_READY = "Memory store is not ready";
|
|
27093
27303
|
var conversationRedactors = /* @__PURE__ */ new Map();
|
|
27094
27304
|
var clientToolFilterCache = /* @__PURE__ */ new Map();
|
|
27095
27305
|
function getConversationRedactor(conversationId, nerDetector) {
|
|
@@ -27234,7 +27444,7 @@ function useChatStorage(options) {
|
|
|
27234
27444
|
[resolvedPiiRedaction]
|
|
27235
27445
|
);
|
|
27236
27446
|
const maskEmbeddingInput = isPiiRedactor(resolvedPiiRedaction) ? maskForEmbedding : void 0;
|
|
27237
|
-
const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
27447
|
+
const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
27238
27448
|
const messagesCollection = (0, import_react5.useMemo)(() => database.get("history"), [database]);
|
|
27239
27449
|
const conversationsCollection = (0, import_react5.useMemo)(
|
|
27240
27450
|
() => database.get("conversations"),
|
|
@@ -27483,6 +27693,7 @@ function useChatStorage(options) {
|
|
|
27483
27693
|
}, [vaultEmbeddingCache]);
|
|
27484
27694
|
const retainVaultMemory = (0, import_react5.useCallback)(
|
|
27485
27695
|
async (input) => {
|
|
27696
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27486
27697
|
if (memoryStore) {
|
|
27487
27698
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
27488
27699
|
if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -27528,6 +27739,7 @@ function useChatStorage(options) {
|
|
|
27528
27739
|
);
|
|
27529
27740
|
const createMemoryVaultTool2 = (0, import_react5.useCallback)(
|
|
27530
27741
|
(options2) => {
|
|
27742
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27531
27743
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
27532
27744
|
return createMemoryVaultTool(
|
|
27533
27745
|
memoryStore ?? vaultCtx,
|
|
@@ -27538,6 +27750,7 @@ function useChatStorage(options) {
|
|
|
27538
27750
|
);
|
|
27539
27751
|
const createRecallTool2 = (0, import_react5.useCallback)(
|
|
27540
27752
|
(toolOptions, callbacks) => {
|
|
27753
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27541
27754
|
if (!getToken && !memoryStore) {
|
|
27542
27755
|
throw new Error("getToken is required for recall tool");
|
|
27543
27756
|
}
|
|
@@ -27583,7 +27796,7 @@ function useChatStorage(options) {
|
|
|
27583
27796
|
);
|
|
27584
27797
|
const recallFn = (0, import_react5.useCallback)(
|
|
27585
27798
|
async (query, options2) => {
|
|
27586
|
-
if (!getToken && !memoryStore) {
|
|
27799
|
+
if (memoryStore === null || !getToken && !memoryStore) {
|
|
27587
27800
|
return {
|
|
27588
27801
|
memories: [],
|
|
27589
27802
|
usedBudget: options2?.budget ?? "low",
|
|
@@ -27632,6 +27845,7 @@ function useChatStorage(options) {
|
|
|
27632
27845
|
);
|
|
27633
27846
|
const getVaultMemories = (0, import_react5.useCallback)(
|
|
27634
27847
|
(options2) => {
|
|
27848
|
+
if (memoryStore === null) return Promise.resolve([]);
|
|
27635
27849
|
if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
|
|
27636
27850
|
const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
|
|
27637
27851
|
if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -27642,7 +27856,8 @@ function useChatStorage(options) {
|
|
|
27642
27856
|
[vaultCtx, memoryStore]
|
|
27643
27857
|
);
|
|
27644
27858
|
const deleteVaultMemory = (0, import_react5.useCallback)(
|
|
27645
|
-
(id) => {
|
|
27859
|
+
async (id) => {
|
|
27860
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27646
27861
|
return memoryStore ? memoryStore.delete(id) : deleteVaultMemoryOp(vaultCtx, id);
|
|
27647
27862
|
},
|
|
27648
27863
|
[vaultCtx, memoryStore]
|