@anuma/sdk 7.0.7 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +224 -68
- package/dist/expo/index.d.mts +24 -4
- package/dist/expo/index.d.ts +24 -4
- package/dist/expo/index.mjs +224 -68
- package/dist/memory/context.d.mts +1 -0
- package/dist/memory/context.d.ts +1 -0
- package/dist/react/index.cjs +229 -68
- package/dist/react/index.d.mts +24 -4
- package/dist/react/index.d.ts +24 -4
- package/dist/react/index.mjs +229 -68
- package/dist/server/index.cjs +144 -28
- package/dist/server/index.d.mts +22 -2
- package/dist/server/index.d.ts +22 -2
- package/dist/server/index.mjs +144 -28
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -27824,6 +27824,11 @@ function parseTopics(value) {
|
|
|
27824
27824
|
}
|
|
27825
27825
|
|
|
27826
27826
|
// src/lib/db/entities/operations.ts
|
|
27827
|
+
async function assertCanWrite(ctx) {
|
|
27828
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
27829
|
+
throw new Error("Memory source is no longer eligible");
|
|
27830
|
+
}
|
|
27831
|
+
}
|
|
27827
27832
|
function entityToStored(e) {
|
|
27828
27833
|
return {
|
|
27829
27834
|
uniqueId: e.id,
|
|
@@ -27964,6 +27969,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
27964
27969
|
let skipped = false;
|
|
27965
27970
|
let entities = [];
|
|
27966
27971
|
await ctx.database.write(async () => {
|
|
27972
|
+
await assertCanWrite(ctx);
|
|
27967
27973
|
const {
|
|
27968
27974
|
entities: byName,
|
|
27969
27975
|
operations: entityOps,
|
|
@@ -28039,6 +28045,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
28039
28045
|
let skipped = false;
|
|
28040
28046
|
let entities = [];
|
|
28041
28047
|
await ctx.database.write(async () => {
|
|
28048
|
+
await assertCanWrite(ctx);
|
|
28042
28049
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
28043
28050
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
28044
28051
|
skipped = true;
|
|
@@ -28099,6 +28106,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
28099
28106
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb18.Q.where("memory_id", import_watermelondb18.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
28100
28107
|
if (links.length === 0) return;
|
|
28101
28108
|
await ctx.database.write(async () => {
|
|
28109
|
+
await assertCanWrite(ctx);
|
|
28102
28110
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
28103
28111
|
});
|
|
28104
28112
|
}
|
|
@@ -28107,6 +28115,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
28107
28115
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb18.Q.where("user_id", userId)).fetch();
|
|
28108
28116
|
if (links.length === 0) return;
|
|
28109
28117
|
await ctx.database.write(async () => {
|
|
28118
|
+
await assertCanWrite(ctx);
|
|
28110
28119
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
28111
28120
|
});
|
|
28112
28121
|
}
|
|
@@ -28282,6 +28291,11 @@ function visibilityConditions(requested) {
|
|
|
28282
28291
|
function isKinded(record) {
|
|
28283
28292
|
return record.kind !== null && record.kind !== void 0;
|
|
28284
28293
|
}
|
|
28294
|
+
async function assertCanWrite2(ctx) {
|
|
28295
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
28296
|
+
throw new Error("Memory source is no longer eligible");
|
|
28297
|
+
}
|
|
28298
|
+
}
|
|
28285
28299
|
function assertValidKindLevel(kind, level) {
|
|
28286
28300
|
const hasKind = kind !== null && kind !== void 0;
|
|
28287
28301
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -28462,8 +28476,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
28462
28476
|
ctx.embeddedWalletSigner
|
|
28463
28477
|
) : opts.content;
|
|
28464
28478
|
const created = await ctx.database.write(async () => {
|
|
28465
|
-
|
|
28466
|
-
throw new Error("Memory source is no longer eligible");
|
|
28479
|
+
await assertCanWrite2(ctx);
|
|
28467
28480
|
return ctx.vaultMemoryCollection.create(
|
|
28468
28481
|
(record) => populateNewVaultMemory(record, ctx, opts, encryptedContent, encryptedKindValue)
|
|
28469
28482
|
);
|
|
@@ -28482,8 +28495,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
28482
28495
|
) : opts.content;
|
|
28483
28496
|
let createdRecord = null;
|
|
28484
28497
|
await ctx.database.write(async () => {
|
|
28485
|
-
|
|
28486
|
-
throw new Error("Memory source is no longer eligible");
|
|
28498
|
+
await assertCanWrite2(ctx);
|
|
28487
28499
|
let target;
|
|
28488
28500
|
try {
|
|
28489
28501
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -28575,8 +28587,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
28575
28587
|
})
|
|
28576
28588
|
);
|
|
28577
28589
|
const created = await ctx.database.write(async () => {
|
|
28578
|
-
|
|
28579
|
-
throw new Error("Memory source is no longer eligible");
|
|
28590
|
+
await assertCanWrite2(ctx);
|
|
28580
28591
|
const prepared = optionsArray.map(
|
|
28581
28592
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
28582
28593
|
(record) => populateNewVaultMemory(record, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -28867,8 +28878,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
28867
28878
|
const record = probe;
|
|
28868
28879
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
28869
28880
|
await ctx.database.write(async () => {
|
|
28870
|
-
|
|
28871
|
-
throw new Error("Memory source is no longer eligible");
|
|
28881
|
+
await assertCanWrite2(ctx);
|
|
28872
28882
|
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record) || opts.freeFormOnly && isKinded(record)) {
|
|
28873
28883
|
stale = true;
|
|
28874
28884
|
return;
|
|
@@ -28979,6 +28989,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
28979
28989
|
let stale = false;
|
|
28980
28990
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
28981
28991
|
await ctx.database.write(async (writer) => {
|
|
28992
|
+
await assertCanWrite2(ctx);
|
|
28982
28993
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
28983
28994
|
stale = true;
|
|
28984
28995
|
return;
|
|
@@ -29020,6 +29031,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
29020
29031
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
29021
29032
|
let cleared = false;
|
|
29022
29033
|
await ctx.database.write(async () => {
|
|
29034
|
+
await assertCanWrite2(ctx);
|
|
29023
29035
|
if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
|
|
29024
29036
|
cleared = true;
|
|
29025
29037
|
await record.update((r) => {
|
|
@@ -29043,6 +29055,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
29043
29055
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
|
|
29044
29056
|
let stale = false;
|
|
29045
29057
|
await ctx.database.write(async () => {
|
|
29058
|
+
await assertCanWrite2(ctx);
|
|
29046
29059
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
29047
29060
|
stale = true;
|
|
29048
29061
|
return;
|
|
@@ -29071,6 +29084,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
29071
29084
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
29072
29085
|
let stale = false;
|
|
29073
29086
|
await ctx.database.write(async () => {
|
|
29087
|
+
await assertCanWrite2(ctx);
|
|
29074
29088
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
29075
29089
|
stale = true;
|
|
29076
29090
|
return;
|
|
@@ -29108,8 +29122,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
29108
29122
|
}
|
|
29109
29123
|
let stale = false;
|
|
29110
29124
|
await ctx.database.write(async () => {
|
|
29111
|
-
|
|
29112
|
-
throw new Error("Memory source is no longer eligible");
|
|
29125
|
+
await assertCanWrite2(ctx);
|
|
29113
29126
|
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
29114
29127
|
stale = true;
|
|
29115
29128
|
return;
|
|
@@ -29271,6 +29284,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
29271
29284
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
29272
29285
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
29273
29286
|
await ctx.database.write(async () => {
|
|
29287
|
+
await assertCanWrite2(ctx);
|
|
29274
29288
|
const records = [];
|
|
29275
29289
|
for (const id of chunkIds) {
|
|
29276
29290
|
try {
|
|
@@ -29304,6 +29318,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
29304
29318
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
29305
29319
|
try {
|
|
29306
29320
|
await ctx.database.write(async (writer) => {
|
|
29321
|
+
await assertCanWrite2(ctx);
|
|
29307
29322
|
let record;
|
|
29308
29323
|
try {
|
|
29309
29324
|
record = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -29334,6 +29349,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
29334
29349
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
29335
29350
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
29336
29351
|
await ctx.database.write(async () => {
|
|
29352
|
+
await assertCanWrite2(ctx);
|
|
29337
29353
|
const writes = [];
|
|
29338
29354
|
for (const id of chunkIds) {
|
|
29339
29355
|
let record;
|
|
@@ -29366,6 +29382,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
29366
29382
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb19.Q.where("user_id", userId), import_watermelondb19.Q.where("is_deleted", false)).fetch();
|
|
29367
29383
|
if (records.length === 0) return 0;
|
|
29368
29384
|
await ctx.database.write(async () => {
|
|
29385
|
+
await assertCanWrite2(ctx);
|
|
29369
29386
|
const prepared = records.map(
|
|
29370
29387
|
(record) => record.prepareUpdate((r) => {
|
|
29371
29388
|
r._setRaw("is_deleted", true);
|
|
@@ -29420,6 +29437,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
29420
29437
|
let stale = false;
|
|
29421
29438
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
29422
29439
|
await ctx.database.write(async () => {
|
|
29440
|
+
await assertCanWrite2(ctx);
|
|
29423
29441
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
|
|
29424
29442
|
stale = true;
|
|
29425
29443
|
return;
|
|
@@ -29443,6 +29461,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
29443
29461
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
29444
29462
|
let stale = false;
|
|
29445
29463
|
await ctx.database.write(async () => {
|
|
29464
|
+
await assertCanWrite2(ctx);
|
|
29446
29465
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
29447
29466
|
stale = true;
|
|
29448
29467
|
return;
|
|
@@ -29463,6 +29482,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
29463
29482
|
const now = opts.now ?? Date.now();
|
|
29464
29483
|
let stale = false;
|
|
29465
29484
|
await ctx.database.write(async () => {
|
|
29485
|
+
await assertCanWrite2(ctx);
|
|
29466
29486
|
const archivedAt = record.archivedAt;
|
|
29467
29487
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
29468
29488
|
stale = true;
|
|
@@ -29502,6 +29522,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
29502
29522
|
}
|
|
29503
29523
|
let written = false;
|
|
29504
29524
|
await ctx.database.write(async () => {
|
|
29525
|
+
await assertCanWrite2(ctx);
|
|
29505
29526
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
|
|
29506
29527
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
29507
29528
|
if (originalUpdatedAt !== readUpdatedAt || record._getRaw("content") !== readStoredContent)
|
|
@@ -33194,6 +33215,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
33194
33215
|
).map((c) => c.candidate);
|
|
33195
33216
|
}
|
|
33196
33217
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
33218
|
+
const { memoryStore, signal } = options;
|
|
33219
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
33220
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
33221
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
33222
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
33223
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
33224
|
+
signal?.throwIfAborted();
|
|
33197
33225
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
33198
33226
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
33199
33227
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -33227,6 +33255,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33227
33255
|
}
|
|
33228
33256
|
});
|
|
33229
33257
|
const extractMs = Date.now() - tExtract;
|
|
33258
|
+
signal?.throwIfAborted();
|
|
33230
33259
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
33231
33260
|
const log = getLogger();
|
|
33232
33261
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -33274,16 +33303,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33274
33303
|
const results = [];
|
|
33275
33304
|
const quarantinedInfo = [];
|
|
33276
33305
|
let failedWrites = 0;
|
|
33306
|
+
let auditRows;
|
|
33277
33307
|
const tRetain = Date.now();
|
|
33278
33308
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
33279
33309
|
try {
|
|
33310
|
+
signal?.throwIfAborted();
|
|
33280
33311
|
if (isQuarantined) {
|
|
33281
|
-
|
|
33282
|
-
|
|
33283
|
-
|
|
33284
|
-
|
|
33285
|
-
|
|
33286
|
-
|
|
33312
|
+
let existingId;
|
|
33313
|
+
if (memoryStore) {
|
|
33314
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
33315
|
+
scopes: [options.scope ?? "private"],
|
|
33316
|
+
includeArchived: true,
|
|
33317
|
+
includeQuarantined: true,
|
|
33318
|
+
includeSuperseded: true
|
|
33319
|
+
}));
|
|
33320
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
33321
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
33322
|
+
existingId = (await auditRows).find(
|
|
33323
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
33324
|
+
)?.uniqueId ?? null;
|
|
33325
|
+
} else {
|
|
33326
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
33327
|
+
retainCtx.vaultCtx,
|
|
33328
|
+
candidate.content,
|
|
33329
|
+
candidate.sourceMessageIds,
|
|
33330
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
33331
|
+
).catch(() => null);
|
|
33332
|
+
}
|
|
33287
33333
|
if (existingId) {
|
|
33288
33334
|
quarantinedInfo.push({
|
|
33289
33335
|
candidate,
|
|
@@ -33294,18 +33340,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33294
33340
|
continue;
|
|
33295
33341
|
}
|
|
33296
33342
|
}
|
|
33297
|
-
const
|
|
33343
|
+
const retainOptions = {
|
|
33298
33344
|
source: "auto-extracted",
|
|
33299
33345
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
33300
33346
|
respectTombstones: true,
|
|
33301
33347
|
...options.scope !== void 0 && { scope: options.scope },
|
|
33302
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
33303
33348
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
33304
33349
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
33305
33350
|
factType: candidate.type,
|
|
33306
33351
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
33352
|
+
};
|
|
33353
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
33354
|
+
...retainOptions,
|
|
33355
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
33356
|
+
signal
|
|
33357
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
33358
|
+
...retainOptions,
|
|
33359
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
33307
33360
|
});
|
|
33308
33361
|
if (isQuarantined) {
|
|
33362
|
+
auditRows = void 0;
|
|
33309
33363
|
const info = {
|
|
33310
33364
|
candidate,
|
|
33311
33365
|
memoryId: result.memoryId,
|
|
@@ -33324,9 +33378,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33324
33378
|
}
|
|
33325
33379
|
succeededCandidates.push(candidate);
|
|
33326
33380
|
results.push(result);
|
|
33327
|
-
if (result.action !== "suppressed" &&
|
|
33381
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
33328
33382
|
try {
|
|
33329
|
-
|
|
33383
|
+
signal?.throwIfAborted();
|
|
33384
|
+
if (memoryStore) {
|
|
33385
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
33386
|
+
unlessUserManaged: true,
|
|
33387
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
33388
|
+
signal
|
|
33389
|
+
});
|
|
33390
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
33330
33391
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
33331
33392
|
unlessTopicsUserManaged: true
|
|
33332
33393
|
});
|
|
@@ -33576,7 +33637,7 @@ function createAutoExtractor(options) {
|
|
|
33576
33637
|
};
|
|
33577
33638
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
33578
33639
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
33579
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
33640
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
33580
33641
|
getLogger().warn(
|
|
33581
33642
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
33582
33643
|
);
|
|
@@ -33621,6 +33682,8 @@ function createAutoExtractor(options) {
|
|
|
33621
33682
|
try {
|
|
33622
33683
|
const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
33623
33684
|
extract,
|
|
33685
|
+
memoryStore: options.memoryStore,
|
|
33686
|
+
signal: options.signal,
|
|
33624
33687
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
33625
33688
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
33626
33689
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -35752,6 +35815,7 @@ function createLocalMemoryStore(options) {
|
|
|
35752
35815
|
database,
|
|
35753
35816
|
entityCollection: database.get("entity"),
|
|
35754
35817
|
memoryEntityCollection: database.get("memory_entity"),
|
|
35818
|
+
canWrite: options.canWrite,
|
|
35755
35819
|
...userId !== void 0 && { userId },
|
|
35756
35820
|
...options.allowUnscopedRows !== void 0 && {
|
|
35757
35821
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -35763,10 +35827,21 @@ function createLocalMemoryStore(options) {
|
|
|
35763
35827
|
walletAddress: options.walletAddress,
|
|
35764
35828
|
signMessage: options.signMessage,
|
|
35765
35829
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
35830
|
+
canWrite: options.canWrite,
|
|
35766
35831
|
...userId !== void 0 && { userId },
|
|
35767
35832
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
35768
35833
|
entityCtx
|
|
35769
35834
|
};
|
|
35835
|
+
const assertWrite = async (writeOptions) => {
|
|
35836
|
+
writeOptions?.signal?.throwIfAborted();
|
|
35837
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
35838
|
+
throw new Error("Memory source is no longer eligible");
|
|
35839
|
+
}
|
|
35840
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
35841
|
+
throw new Error("Memory source is no longer eligible");
|
|
35842
|
+
}
|
|
35843
|
+
writeOptions?.signal?.throwIfAborted();
|
|
35844
|
+
};
|
|
35770
35845
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
35771
35846
|
const ownedBy = userId !== void 0 ? [import_watermelondb24.Q.where("user_id", userId)] : [];
|
|
35772
35847
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb24.Q.or(import_watermelondb24.Q.where("user_id", userId), import_watermelondb24.Q.where("user_id", null))] : [import_watermelondb24.Q.where("user_id", userId)];
|
|
@@ -35878,9 +35953,25 @@ function createLocalMemoryStore(options) {
|
|
|
35878
35953
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
35879
35954
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
35880
35955
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
35881
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
35956
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
35957
|
+
await assertWrite(writeOptions);
|
|
35882
35958
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb24.Q.where("id", memoryId), import_watermelondb24.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
35883
|
-
return owned > 0 ? writer.callWriter(
|
|
35959
|
+
return owned > 0 ? writer.callWriter(
|
|
35960
|
+
() => linkMemoryEntitiesOp(
|
|
35961
|
+
{
|
|
35962
|
+
...entityCtx,
|
|
35963
|
+
canWrite: async () => {
|
|
35964
|
+
await assertWrite(writeOptions);
|
|
35965
|
+
return true;
|
|
35966
|
+
}
|
|
35967
|
+
},
|
|
35968
|
+
memoryId,
|
|
35969
|
+
topics,
|
|
35970
|
+
{
|
|
35971
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
35972
|
+
}
|
|
35973
|
+
)
|
|
35974
|
+
) : [];
|
|
35884
35975
|
}),
|
|
35885
35976
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
35886
35977
|
recall: (query, recallOptions) => recall(
|
|
@@ -35890,7 +35981,17 @@ function createLocalMemoryStore(options) {
|
|
|
35890
35981
|
),
|
|
35891
35982
|
retain: (content, retainOptions) => retain(
|
|
35892
35983
|
content,
|
|
35893
|
-
{
|
|
35984
|
+
{
|
|
35985
|
+
vaultCtx: {
|
|
35986
|
+
...vaultCtx,
|
|
35987
|
+
canWrite: async () => {
|
|
35988
|
+
await assertWrite(retainOptions);
|
|
35989
|
+
return true;
|
|
35990
|
+
}
|
|
35991
|
+
},
|
|
35992
|
+
embeddingOptions: options.embeddingOptions,
|
|
35993
|
+
vaultCache
|
|
35994
|
+
},
|
|
35894
35995
|
retainOptions
|
|
35895
35996
|
),
|
|
35896
35997
|
factSource: {
|
|
@@ -36742,6 +36843,7 @@ function createDurableAutoExtractor(options) {
|
|
|
36742
36843
|
};
|
|
36743
36844
|
const folderId = options.folderId ?? null;
|
|
36744
36845
|
let disposed = false;
|
|
36846
|
+
let activeBatch = null;
|
|
36745
36847
|
let running = false;
|
|
36746
36848
|
let wakeRequested = false;
|
|
36747
36849
|
let timer;
|
|
@@ -36778,14 +36880,18 @@ function createDurableAutoExtractor(options) {
|
|
|
36778
36880
|
}, delay);
|
|
36779
36881
|
}
|
|
36780
36882
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
36883
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
36781
36884
|
let watchdog;
|
|
36782
36885
|
let cancelled = false;
|
|
36886
|
+
const controller = new AbortController();
|
|
36887
|
+
activeBatch = controller;
|
|
36783
36888
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
36784
36889
|
try {
|
|
36785
36890
|
return await Promise.race([
|
|
36786
36891
|
new Promise((resolve, reject) => {
|
|
36787
36892
|
const worker = createAutoExtractor({
|
|
36788
36893
|
...options,
|
|
36894
|
+
signal: controller.signal,
|
|
36789
36895
|
retainCtx: {
|
|
36790
36896
|
...options.retainCtx,
|
|
36791
36897
|
vaultCtx: {
|
|
@@ -36814,6 +36920,8 @@ function createDurableAutoExtractor(options) {
|
|
|
36814
36920
|
]);
|
|
36815
36921
|
} finally {
|
|
36816
36922
|
cancelled = true;
|
|
36923
|
+
controller.abort();
|
|
36924
|
+
if (activeBatch === controller) activeBatch = null;
|
|
36817
36925
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
36818
36926
|
}
|
|
36819
36927
|
}
|
|
@@ -36825,6 +36933,7 @@ function createDurableAutoExtractor(options) {
|
|
|
36825
36933
|
for (const message of loaded)
|
|
36826
36934
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
36827
36935
|
await database.write(async () => {
|
|
36936
|
+
if (disposed) return;
|
|
36828
36937
|
const current = idsOf(job);
|
|
36829
36938
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
36830
36939
|
if (!acknowledged.length) return;
|
|
@@ -36997,6 +37106,7 @@ function createDurableAutoExtractor(options) {
|
|
|
36997
37106
|
jobScope,
|
|
36998
37107
|
jobFolderId
|
|
36999
37108
|
);
|
|
37109
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
37000
37110
|
options.onTurnComplete?.(result);
|
|
37001
37111
|
return result;
|
|
37002
37112
|
};
|
|
@@ -37033,6 +37143,7 @@ function createDurableAutoExtractor(options) {
|
|
|
37033
37143
|
);
|
|
37034
37144
|
scheduleAfterSuccess = true;
|
|
37035
37145
|
} catch (error) {
|
|
37146
|
+
if (disposed) break;
|
|
37036
37147
|
attempts.set(job.id, attempted + 1);
|
|
37037
37148
|
retry = true;
|
|
37038
37149
|
reportError(error, conversationId);
|
|
@@ -37055,6 +37166,14 @@ function createDurableAutoExtractor(options) {
|
|
|
37055
37166
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
37056
37167
|
}
|
|
37057
37168
|
}
|
|
37169
|
+
function dispose() {
|
|
37170
|
+
disposed = true;
|
|
37171
|
+
activeBatch?.abort(options.signal?.reason);
|
|
37172
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
37173
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
37174
|
+
}
|
|
37175
|
+
if (options.signal?.aborted) dispose();
|
|
37176
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
37058
37177
|
schedule(0);
|
|
37059
37178
|
return {
|
|
37060
37179
|
processTurn(messages, conversationId) {
|
|
@@ -37134,10 +37253,7 @@ function createDurableAutoExtractor(options) {
|
|
|
37134
37253
|
return true;
|
|
37135
37254
|
},
|
|
37136
37255
|
isProcessing: () => running,
|
|
37137
|
-
dispose
|
|
37138
|
-
disposed = true;
|
|
37139
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
37140
|
-
}
|
|
37256
|
+
dispose
|
|
37141
37257
|
};
|
|
37142
37258
|
}
|
|
37143
37259
|
|
package/dist/server/index.d.mts
CHANGED
|
@@ -2779,6 +2779,7 @@ interface EntityOperationsContext {
|
|
|
2779
2779
|
* (server / SQLite, where the migration backfill is authoritative).
|
|
2780
2780
|
*/
|
|
2781
2781
|
allowUnscopedRows?: boolean;
|
|
2782
|
+
canWrite?: () => Promise<boolean>;
|
|
2782
2783
|
}
|
|
2783
2784
|
|
|
2784
2785
|
/**
|
|
@@ -4933,6 +4934,10 @@ type ExtractOutcome = "extracted" | "no-facts" | "empty-after-retry" | "dropped-
|
|
|
4933
4934
|
*/
|
|
4934
4935
|
declare function extractAndRetain(messages: AutoExtractMessage[], retainCtx: RetainContext, options: {
|
|
4935
4936
|
extract: ExtractFactsOptions;
|
|
4937
|
+
/** Route extracted facts through this store instead of the local vault. */
|
|
4938
|
+
memoryStore?: MemoryStore | null;
|
|
4939
|
+
/** Cancel remote writes for this extraction batch. */
|
|
4940
|
+
signal?: AbortSignal;
|
|
4936
4941
|
minConfidence?: number;
|
|
4937
4942
|
/** Override scope/folder for all retained facts. */
|
|
4938
4943
|
scope?: string;
|
|
@@ -6180,7 +6185,12 @@ type MemoryRecallOptions = Omit<RecallOptions, "types" | "includeChunks" | "conv
|
|
|
6180
6185
|
* and never receives these credentials, callbacks or redactor instances.
|
|
6181
6186
|
* @public
|
|
6182
6187
|
*/
|
|
6183
|
-
type MemoryRetainOptions = Omit<RetainOptions, "folderId"
|
|
6188
|
+
type MemoryRetainOptions = Omit<RetainOptions, "folderId"> & {
|
|
6189
|
+
/** Reject writes when the originating extraction is no longer eligible. */
|
|
6190
|
+
canWrite?: () => Promise<boolean>;
|
|
6191
|
+
/** Abort pending remote requests when the originating extraction is cancelled. */
|
|
6192
|
+
signal?: AbortSignal;
|
|
6193
|
+
};
|
|
6184
6194
|
/**
|
|
6185
6195
|
* A topic and how many memories link to it.
|
|
6186
6196
|
* @public
|
|
@@ -6309,7 +6319,11 @@ interface MemoryStore {
|
|
|
6309
6319
|
/** Replace the memory's topics with a user-chosen set and stop auto-tagging it. */
|
|
6310
6320
|
setTopics(memoryId: string, topics: readonly EntityInput[]): Promise<StoredVaultMemory | null>;
|
|
6311
6321
|
/** Add topics alongside the existing ones (auto-tagging stays on). */
|
|
6312
|
-
addTopics(memoryId: string, topics: readonly EntityInput[]
|
|
6322
|
+
addTopics(memoryId: string, topics: readonly EntityInput[], options?: {
|
|
6323
|
+
unlessUserManaged?: boolean;
|
|
6324
|
+
canWrite?: () => Promise<boolean>;
|
|
6325
|
+
signal?: AbortSignal;
|
|
6326
|
+
}): Promise<StoredEntity[]>;
|
|
6313
6327
|
setVisibility(id: string, visibility: VaultMemoryVisibility, options?: {
|
|
6314
6328
|
twinOptIn?: boolean;
|
|
6315
6329
|
}): Promise<StoredVaultMemory | null>;
|
|
@@ -9079,6 +9093,10 @@ interface SyncKeyValueStore {
|
|
|
9079
9093
|
declare function createPlatformCursorStore(storage: SyncKeyValueStore, keyPrefix?: string): ExtractionCursorStore;
|
|
9080
9094
|
interface CreateAutoExtractorOptions {
|
|
9081
9095
|
retainCtx: RetainContext;
|
|
9096
|
+
/** Route retained facts and topics through this store; null disables memory writes. */
|
|
9097
|
+
memoryStore?: MemoryStore | null;
|
|
9098
|
+
/** Cancel remote writes for an extraction batch. */
|
|
9099
|
+
signal?: AbortSignal;
|
|
9082
9100
|
extract: ExtractFactsOptions;
|
|
9083
9101
|
/** Confidence floor for retained facts. Default 0.7. */
|
|
9084
9102
|
minConfidence?: number;
|
|
@@ -9686,6 +9704,8 @@ interface LocalMemoryStoreOptions {
|
|
|
9686
9704
|
walletAddress?: string;
|
|
9687
9705
|
signMessage?: SignMessageFn;
|
|
9688
9706
|
embeddedWalletSigner?: EmbeddedWalletSignerFn;
|
|
9707
|
+
/** Rechecked inside each serialized memory write. */
|
|
9708
|
+
canWrite?: () => Promise<boolean>;
|
|
9689
9709
|
/**
|
|
9690
9710
|
* Scope every read/write to this user — for a shared, multi-tenant database
|
|
9691
9711
|
* whose rows all carry their `user_id`. Rows with no `user_id` are invisible
|
package/dist/server/index.d.ts
CHANGED
|
@@ -2779,6 +2779,7 @@ interface EntityOperationsContext {
|
|
|
2779
2779
|
* (server / SQLite, where the migration backfill is authoritative).
|
|
2780
2780
|
*/
|
|
2781
2781
|
allowUnscopedRows?: boolean;
|
|
2782
|
+
canWrite?: () => Promise<boolean>;
|
|
2782
2783
|
}
|
|
2783
2784
|
|
|
2784
2785
|
/**
|
|
@@ -4933,6 +4934,10 @@ type ExtractOutcome = "extracted" | "no-facts" | "empty-after-retry" | "dropped-
|
|
|
4933
4934
|
*/
|
|
4934
4935
|
declare function extractAndRetain(messages: AutoExtractMessage[], retainCtx: RetainContext, options: {
|
|
4935
4936
|
extract: ExtractFactsOptions;
|
|
4937
|
+
/** Route extracted facts through this store instead of the local vault. */
|
|
4938
|
+
memoryStore?: MemoryStore | null;
|
|
4939
|
+
/** Cancel remote writes for this extraction batch. */
|
|
4940
|
+
signal?: AbortSignal;
|
|
4936
4941
|
minConfidence?: number;
|
|
4937
4942
|
/** Override scope/folder for all retained facts. */
|
|
4938
4943
|
scope?: string;
|
|
@@ -6180,7 +6185,12 @@ type MemoryRecallOptions = Omit<RecallOptions, "types" | "includeChunks" | "conv
|
|
|
6180
6185
|
* and never receives these credentials, callbacks or redactor instances.
|
|
6181
6186
|
* @public
|
|
6182
6187
|
*/
|
|
6183
|
-
type MemoryRetainOptions = Omit<RetainOptions, "folderId"
|
|
6188
|
+
type MemoryRetainOptions = Omit<RetainOptions, "folderId"> & {
|
|
6189
|
+
/** Reject writes when the originating extraction is no longer eligible. */
|
|
6190
|
+
canWrite?: () => Promise<boolean>;
|
|
6191
|
+
/** Abort pending remote requests when the originating extraction is cancelled. */
|
|
6192
|
+
signal?: AbortSignal;
|
|
6193
|
+
};
|
|
6184
6194
|
/**
|
|
6185
6195
|
* A topic and how many memories link to it.
|
|
6186
6196
|
* @public
|
|
@@ -6309,7 +6319,11 @@ interface MemoryStore {
|
|
|
6309
6319
|
/** Replace the memory's topics with a user-chosen set and stop auto-tagging it. */
|
|
6310
6320
|
setTopics(memoryId: string, topics: readonly EntityInput[]): Promise<StoredVaultMemory | null>;
|
|
6311
6321
|
/** Add topics alongside the existing ones (auto-tagging stays on). */
|
|
6312
|
-
addTopics(memoryId: string, topics: readonly EntityInput[]
|
|
6322
|
+
addTopics(memoryId: string, topics: readonly EntityInput[], options?: {
|
|
6323
|
+
unlessUserManaged?: boolean;
|
|
6324
|
+
canWrite?: () => Promise<boolean>;
|
|
6325
|
+
signal?: AbortSignal;
|
|
6326
|
+
}): Promise<StoredEntity[]>;
|
|
6313
6327
|
setVisibility(id: string, visibility: VaultMemoryVisibility, options?: {
|
|
6314
6328
|
twinOptIn?: boolean;
|
|
6315
6329
|
}): Promise<StoredVaultMemory | null>;
|
|
@@ -9079,6 +9093,10 @@ interface SyncKeyValueStore {
|
|
|
9079
9093
|
declare function createPlatformCursorStore(storage: SyncKeyValueStore, keyPrefix?: string): ExtractionCursorStore;
|
|
9080
9094
|
interface CreateAutoExtractorOptions {
|
|
9081
9095
|
retainCtx: RetainContext;
|
|
9096
|
+
/** Route retained facts and topics through this store; null disables memory writes. */
|
|
9097
|
+
memoryStore?: MemoryStore | null;
|
|
9098
|
+
/** Cancel remote writes for an extraction batch. */
|
|
9099
|
+
signal?: AbortSignal;
|
|
9082
9100
|
extract: ExtractFactsOptions;
|
|
9083
9101
|
/** Confidence floor for retained facts. Default 0.7. */
|
|
9084
9102
|
minConfidence?: number;
|
|
@@ -9686,6 +9704,8 @@ interface LocalMemoryStoreOptions {
|
|
|
9686
9704
|
walletAddress?: string;
|
|
9687
9705
|
signMessage?: SignMessageFn;
|
|
9688
9706
|
embeddedWalletSigner?: EmbeddedWalletSignerFn;
|
|
9707
|
+
/** Rechecked inside each serialized memory write. */
|
|
9708
|
+
canWrite?: () => Promise<boolean>;
|
|
9689
9709
|
/**
|
|
9690
9710
|
* Scope every read/write to this user — for a shared, multi-tenant database
|
|
9691
9711
|
* whose rows all carry their `user_id`. Rows with no `user_id` are invisible
|