@anuma/sdk 7.0.6 → 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 +365 -112
- package/dist/expo/index.d.mts +34 -4
- package/dist/expo/index.d.ts +34 -4
- package/dist/expo/index.mjs +362 -112
- package/dist/memory/context.d.mts +1 -0
- package/dist/memory/context.d.ts +1 -0
- package/dist/react/index.cjs +370 -112
- package/dist/react/index.d.mts +34 -4
- package/dist/react/index.d.ts +34 -4
- package/dist/react/index.mjs +367 -112
- package/dist/server/index.cjs +157 -30
- package/dist/server/index.d.mts +22 -2
- package/dist/server/index.d.ts +22 -2
- package/dist/server/index.mjs +157 -30
- 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
|
}
|
|
@@ -28199,6 +28208,17 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
28199
28208
|
};
|
|
28200
28209
|
}
|
|
28201
28210
|
|
|
28211
|
+
// src/lib/db/memoryVault/sourceChunkIds.ts
|
|
28212
|
+
var MAX_SOURCE_CHUNK_IDS_BYTES = 16 << 10;
|
|
28213
|
+
var utf8 = new TextEncoder();
|
|
28214
|
+
function serializeSourceChunkIds(ids) {
|
|
28215
|
+
const sizes = ids.map((id) => utf8.encode(JSON.stringify(id)).length + 1);
|
|
28216
|
+
let total = sizes.reduce((sum, size) => sum + size, 1);
|
|
28217
|
+
let start = 0;
|
|
28218
|
+
while (total > MAX_SOURCE_CHUNK_IDS_BYTES && start < ids.length) total -= sizes[start++];
|
|
28219
|
+
return JSON.stringify(ids.slice(start));
|
|
28220
|
+
}
|
|
28221
|
+
|
|
28202
28222
|
// src/lib/db/memoryVault/types.ts
|
|
28203
28223
|
var MEMORY_KINDS = [
|
|
28204
28224
|
"display_name",
|
|
@@ -28271,6 +28291,11 @@ function visibilityConditions(requested) {
|
|
|
28271
28291
|
function isKinded(record) {
|
|
28272
28292
|
return record.kind !== null && record.kind !== void 0;
|
|
28273
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
|
+
}
|
|
28274
28299
|
function assertValidKindLevel(kind, level) {
|
|
28275
28300
|
const hasKind = kind !== null && kind !== void 0;
|
|
28276
28301
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -28417,7 +28442,7 @@ function populateNewVaultMemory(record, ctx, opts, encryptedContent, encryptedKi
|
|
|
28417
28442
|
record._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
28418
28443
|
}
|
|
28419
28444
|
if (opts.sourceChunkIds !== void 0) {
|
|
28420
|
-
record._setRaw("source_chunk_ids",
|
|
28445
|
+
record._setRaw("source_chunk_ids", serializeSourceChunkIds(opts.sourceChunkIds));
|
|
28421
28446
|
}
|
|
28422
28447
|
record._setRaw("proof_count", opts.proofCount ?? 1);
|
|
28423
28448
|
record._setRaw("source", opts.source ?? "manual");
|
|
@@ -28451,8 +28476,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
28451
28476
|
ctx.embeddedWalletSigner
|
|
28452
28477
|
) : opts.content;
|
|
28453
28478
|
const created = await ctx.database.write(async () => {
|
|
28454
|
-
|
|
28455
|
-
throw new Error("Memory source is no longer eligible");
|
|
28479
|
+
await assertCanWrite2(ctx);
|
|
28456
28480
|
return ctx.vaultMemoryCollection.create(
|
|
28457
28481
|
(record) => populateNewVaultMemory(record, ctx, opts, encryptedContent, encryptedKindValue)
|
|
28458
28482
|
);
|
|
@@ -28471,8 +28495,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
28471
28495
|
) : opts.content;
|
|
28472
28496
|
let createdRecord = null;
|
|
28473
28497
|
await ctx.database.write(async () => {
|
|
28474
|
-
|
|
28475
|
-
throw new Error("Memory source is no longer eligible");
|
|
28498
|
+
await assertCanWrite2(ctx);
|
|
28476
28499
|
let target;
|
|
28477
28500
|
try {
|
|
28478
28501
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -28564,8 +28587,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
28564
28587
|
})
|
|
28565
28588
|
);
|
|
28566
28589
|
const created = await ctx.database.write(async () => {
|
|
28567
|
-
|
|
28568
|
-
throw new Error("Memory source is no longer eligible");
|
|
28590
|
+
await assertCanWrite2(ctx);
|
|
28569
28591
|
const prepared = optionsArray.map(
|
|
28570
28592
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
28571
28593
|
(record) => populateNewVaultMemory(record, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -28856,8 +28878,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
28856
28878
|
const record = probe;
|
|
28857
28879
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
28858
28880
|
await ctx.database.write(async () => {
|
|
28859
|
-
|
|
28860
|
-
throw new Error("Memory source is no longer eligible");
|
|
28881
|
+
await assertCanWrite2(ctx);
|
|
28861
28882
|
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record) || opts.freeFormOnly && isKinded(record)) {
|
|
28862
28883
|
stale = true;
|
|
28863
28884
|
return;
|
|
@@ -28901,7 +28922,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
28901
28922
|
if (opts.sourceChunkIds !== void 0) {
|
|
28902
28923
|
r._setRaw(
|
|
28903
28924
|
"source_chunk_ids",
|
|
28904
|
-
|
|
28925
|
+
serializeSourceChunkIds(
|
|
28905
28926
|
opts.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observedSources, ...opts.sourceChunkIds])] : opts.sourceChunkIds
|
|
28906
28927
|
)
|
|
28907
28928
|
);
|
|
@@ -28968,6 +28989,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
28968
28989
|
let stale = false;
|
|
28969
28990
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
28970
28991
|
await ctx.database.write(async (writer) => {
|
|
28992
|
+
await assertCanWrite2(ctx);
|
|
28971
28993
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
28972
28994
|
stale = true;
|
|
28973
28995
|
return;
|
|
@@ -29009,6 +29031,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
29009
29031
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
29010
29032
|
let cleared = false;
|
|
29011
29033
|
await ctx.database.write(async () => {
|
|
29034
|
+
await assertCanWrite2(ctx);
|
|
29012
29035
|
if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
|
|
29013
29036
|
cleared = true;
|
|
29014
29037
|
await record.update((r) => {
|
|
@@ -29032,6 +29055,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
29032
29055
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
|
|
29033
29056
|
let stale = false;
|
|
29034
29057
|
await ctx.database.write(async () => {
|
|
29058
|
+
await assertCanWrite2(ctx);
|
|
29035
29059
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
29036
29060
|
stale = true;
|
|
29037
29061
|
return;
|
|
@@ -29060,6 +29084,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
29060
29084
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
29061
29085
|
let stale = false;
|
|
29062
29086
|
await ctx.database.write(async () => {
|
|
29087
|
+
await assertCanWrite2(ctx);
|
|
29063
29088
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
29064
29089
|
stale = true;
|
|
29065
29090
|
return;
|
|
@@ -29097,8 +29122,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
29097
29122
|
}
|
|
29098
29123
|
let stale = false;
|
|
29099
29124
|
await ctx.database.write(async () => {
|
|
29100
|
-
|
|
29101
|
-
throw new Error("Memory source is no longer eligible");
|
|
29125
|
+
await assertCanWrite2(ctx);
|
|
29102
29126
|
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
29103
29127
|
stale = true;
|
|
29104
29128
|
return;
|
|
@@ -29260,6 +29284,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
29260
29284
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
29261
29285
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
29262
29286
|
await ctx.database.write(async () => {
|
|
29287
|
+
await assertCanWrite2(ctx);
|
|
29263
29288
|
const records = [];
|
|
29264
29289
|
for (const id of chunkIds) {
|
|
29265
29290
|
try {
|
|
@@ -29293,6 +29318,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
29293
29318
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
29294
29319
|
try {
|
|
29295
29320
|
await ctx.database.write(async (writer) => {
|
|
29321
|
+
await assertCanWrite2(ctx);
|
|
29296
29322
|
let record;
|
|
29297
29323
|
try {
|
|
29298
29324
|
record = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -29323,6 +29349,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
29323
29349
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
29324
29350
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
29325
29351
|
await ctx.database.write(async () => {
|
|
29352
|
+
await assertCanWrite2(ctx);
|
|
29326
29353
|
const writes = [];
|
|
29327
29354
|
for (const id of chunkIds) {
|
|
29328
29355
|
let record;
|
|
@@ -29355,6 +29382,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
29355
29382
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb19.Q.where("user_id", userId), import_watermelondb19.Q.where("is_deleted", false)).fetch();
|
|
29356
29383
|
if (records.length === 0) return 0;
|
|
29357
29384
|
await ctx.database.write(async () => {
|
|
29385
|
+
await assertCanWrite2(ctx);
|
|
29358
29386
|
const prepared = records.map(
|
|
29359
29387
|
(record) => record.prepareUpdate((r) => {
|
|
29360
29388
|
r._setRaw("is_deleted", true);
|
|
@@ -29409,6 +29437,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
29409
29437
|
let stale = false;
|
|
29410
29438
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
29411
29439
|
await ctx.database.write(async () => {
|
|
29440
|
+
await assertCanWrite2(ctx);
|
|
29412
29441
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
|
|
29413
29442
|
stale = true;
|
|
29414
29443
|
return;
|
|
@@ -29432,6 +29461,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
29432
29461
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
29433
29462
|
let stale = false;
|
|
29434
29463
|
await ctx.database.write(async () => {
|
|
29464
|
+
await assertCanWrite2(ctx);
|
|
29435
29465
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
29436
29466
|
stale = true;
|
|
29437
29467
|
return;
|
|
@@ -29452,6 +29482,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
29452
29482
|
const now = opts.now ?? Date.now();
|
|
29453
29483
|
let stale = false;
|
|
29454
29484
|
await ctx.database.write(async () => {
|
|
29485
|
+
await assertCanWrite2(ctx);
|
|
29455
29486
|
const archivedAt = record.archivedAt;
|
|
29456
29487
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
29457
29488
|
stale = true;
|
|
@@ -29491,6 +29522,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
29491
29522
|
}
|
|
29492
29523
|
let written = false;
|
|
29493
29524
|
await ctx.database.write(async () => {
|
|
29525
|
+
await assertCanWrite2(ctx);
|
|
29494
29526
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
|
|
29495
29527
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
29496
29528
|
if (originalUpdatedAt !== readUpdatedAt || record._getRaw("content") !== readStoredContent)
|
|
@@ -33183,6 +33215,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
33183
33215
|
).map((c) => c.candidate);
|
|
33184
33216
|
}
|
|
33185
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();
|
|
33186
33225
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
33187
33226
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
33188
33227
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -33216,6 +33255,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33216
33255
|
}
|
|
33217
33256
|
});
|
|
33218
33257
|
const extractMs = Date.now() - tExtract;
|
|
33258
|
+
signal?.throwIfAborted();
|
|
33219
33259
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
33220
33260
|
const log = getLogger();
|
|
33221
33261
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -33263,16 +33303,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33263
33303
|
const results = [];
|
|
33264
33304
|
const quarantinedInfo = [];
|
|
33265
33305
|
let failedWrites = 0;
|
|
33306
|
+
let auditRows;
|
|
33266
33307
|
const tRetain = Date.now();
|
|
33267
33308
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
33268
33309
|
try {
|
|
33310
|
+
signal?.throwIfAborted();
|
|
33269
33311
|
if (isQuarantined) {
|
|
33270
|
-
|
|
33271
|
-
|
|
33272
|
-
|
|
33273
|
-
|
|
33274
|
-
|
|
33275
|
-
|
|
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
|
+
}
|
|
33276
33333
|
if (existingId) {
|
|
33277
33334
|
quarantinedInfo.push({
|
|
33278
33335
|
candidate,
|
|
@@ -33283,18 +33340,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33283
33340
|
continue;
|
|
33284
33341
|
}
|
|
33285
33342
|
}
|
|
33286
|
-
const
|
|
33343
|
+
const retainOptions = {
|
|
33287
33344
|
source: "auto-extracted",
|
|
33288
33345
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
33289
33346
|
respectTombstones: true,
|
|
33290
33347
|
...options.scope !== void 0 && { scope: options.scope },
|
|
33291
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
33292
33348
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
33293
33349
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
33294
33350
|
factType: candidate.type,
|
|
33295
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 }
|
|
33296
33360
|
});
|
|
33297
33361
|
if (isQuarantined) {
|
|
33362
|
+
auditRows = void 0;
|
|
33298
33363
|
const info = {
|
|
33299
33364
|
candidate,
|
|
33300
33365
|
memoryId: result.memoryId,
|
|
@@ -33313,9 +33378,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
33313
33378
|
}
|
|
33314
33379
|
succeededCandidates.push(candidate);
|
|
33315
33380
|
results.push(result);
|
|
33316
|
-
if (result.action !== "suppressed" &&
|
|
33381
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
33317
33382
|
try {
|
|
33318
|
-
|
|
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)) {
|
|
33319
33391
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
33320
33392
|
unlessTopicsUserManaged: true
|
|
33321
33393
|
});
|
|
@@ -33565,7 +33637,7 @@ function createAutoExtractor(options) {
|
|
|
33565
33637
|
};
|
|
33566
33638
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
33567
33639
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
33568
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
33640
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
33569
33641
|
getLogger().warn(
|
|
33570
33642
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
33571
33643
|
);
|
|
@@ -33610,6 +33682,8 @@ function createAutoExtractor(options) {
|
|
|
33610
33682
|
try {
|
|
33611
33683
|
const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
33612
33684
|
extract,
|
|
33685
|
+
memoryStore: options.memoryStore,
|
|
33686
|
+
signal: options.signal,
|
|
33613
33687
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
33614
33688
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
33615
33689
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -35741,6 +35815,7 @@ function createLocalMemoryStore(options) {
|
|
|
35741
35815
|
database,
|
|
35742
35816
|
entityCollection: database.get("entity"),
|
|
35743
35817
|
memoryEntityCollection: database.get("memory_entity"),
|
|
35818
|
+
canWrite: options.canWrite,
|
|
35744
35819
|
...userId !== void 0 && { userId },
|
|
35745
35820
|
...options.allowUnscopedRows !== void 0 && {
|
|
35746
35821
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -35752,10 +35827,21 @@ function createLocalMemoryStore(options) {
|
|
|
35752
35827
|
walletAddress: options.walletAddress,
|
|
35753
35828
|
signMessage: options.signMessage,
|
|
35754
35829
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
35830
|
+
canWrite: options.canWrite,
|
|
35755
35831
|
...userId !== void 0 && { userId },
|
|
35756
35832
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
35757
35833
|
entityCtx
|
|
35758
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
|
+
};
|
|
35759
35845
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
35760
35846
|
const ownedBy = userId !== void 0 ? [import_watermelondb24.Q.where("user_id", userId)] : [];
|
|
35761
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)];
|
|
@@ -35867,9 +35953,25 @@ function createLocalMemoryStore(options) {
|
|
|
35867
35953
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
35868
35954
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
35869
35955
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
35870
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
35956
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
35957
|
+
await assertWrite(writeOptions);
|
|
35871
35958
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb24.Q.where("id", memoryId), import_watermelondb24.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
35872
|
-
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
|
+
) : [];
|
|
35873
35975
|
}),
|
|
35874
35976
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
35875
35977
|
recall: (query, recallOptions) => recall(
|
|
@@ -35879,7 +35981,17 @@ function createLocalMemoryStore(options) {
|
|
|
35879
35981
|
),
|
|
35880
35982
|
retain: (content, retainOptions) => retain(
|
|
35881
35983
|
content,
|
|
35882
|
-
{
|
|
35984
|
+
{
|
|
35985
|
+
vaultCtx: {
|
|
35986
|
+
...vaultCtx,
|
|
35987
|
+
canWrite: async () => {
|
|
35988
|
+
await assertWrite(retainOptions);
|
|
35989
|
+
return true;
|
|
35990
|
+
}
|
|
35991
|
+
},
|
|
35992
|
+
embeddingOptions: options.embeddingOptions,
|
|
35993
|
+
vaultCache
|
|
35994
|
+
},
|
|
35883
35995
|
retainOptions
|
|
35884
35996
|
),
|
|
35885
35997
|
factSource: {
|
|
@@ -36731,6 +36843,7 @@ function createDurableAutoExtractor(options) {
|
|
|
36731
36843
|
};
|
|
36732
36844
|
const folderId = options.folderId ?? null;
|
|
36733
36845
|
let disposed = false;
|
|
36846
|
+
let activeBatch = null;
|
|
36734
36847
|
let running = false;
|
|
36735
36848
|
let wakeRequested = false;
|
|
36736
36849
|
let timer;
|
|
@@ -36767,14 +36880,18 @@ function createDurableAutoExtractor(options) {
|
|
|
36767
36880
|
}, delay);
|
|
36768
36881
|
}
|
|
36769
36882
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
36883
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
36770
36884
|
let watchdog;
|
|
36771
36885
|
let cancelled = false;
|
|
36886
|
+
const controller = new AbortController();
|
|
36887
|
+
activeBatch = controller;
|
|
36772
36888
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
36773
36889
|
try {
|
|
36774
36890
|
return await Promise.race([
|
|
36775
36891
|
new Promise((resolve, reject) => {
|
|
36776
36892
|
const worker = createAutoExtractor({
|
|
36777
36893
|
...options,
|
|
36894
|
+
signal: controller.signal,
|
|
36778
36895
|
retainCtx: {
|
|
36779
36896
|
...options.retainCtx,
|
|
36780
36897
|
vaultCtx: {
|
|
@@ -36803,6 +36920,8 @@ function createDurableAutoExtractor(options) {
|
|
|
36803
36920
|
]);
|
|
36804
36921
|
} finally {
|
|
36805
36922
|
cancelled = true;
|
|
36923
|
+
controller.abort();
|
|
36924
|
+
if (activeBatch === controller) activeBatch = null;
|
|
36806
36925
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
36807
36926
|
}
|
|
36808
36927
|
}
|
|
@@ -36814,6 +36933,7 @@ function createDurableAutoExtractor(options) {
|
|
|
36814
36933
|
for (const message of loaded)
|
|
36815
36934
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
36816
36935
|
await database.write(async () => {
|
|
36936
|
+
if (disposed) return;
|
|
36817
36937
|
const current = idsOf(job);
|
|
36818
36938
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
36819
36939
|
if (!acknowledged.length) return;
|
|
@@ -36986,6 +37106,7 @@ function createDurableAutoExtractor(options) {
|
|
|
36986
37106
|
jobScope,
|
|
36987
37107
|
jobFolderId
|
|
36988
37108
|
);
|
|
37109
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
36989
37110
|
options.onTurnComplete?.(result);
|
|
36990
37111
|
return result;
|
|
36991
37112
|
};
|
|
@@ -37022,6 +37143,7 @@ function createDurableAutoExtractor(options) {
|
|
|
37022
37143
|
);
|
|
37023
37144
|
scheduleAfterSuccess = true;
|
|
37024
37145
|
} catch (error) {
|
|
37146
|
+
if (disposed) break;
|
|
37025
37147
|
attempts.set(job.id, attempted + 1);
|
|
37026
37148
|
retry = true;
|
|
37027
37149
|
reportError(error, conversationId);
|
|
@@ -37044,6 +37166,14 @@ function createDurableAutoExtractor(options) {
|
|
|
37044
37166
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
37045
37167
|
}
|
|
37046
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 });
|
|
37047
37177
|
schedule(0);
|
|
37048
37178
|
return {
|
|
37049
37179
|
processTurn(messages, conversationId) {
|
|
@@ -37123,10 +37253,7 @@ function createDurableAutoExtractor(options) {
|
|
|
37123
37253
|
return true;
|
|
37124
37254
|
},
|
|
37125
37255
|
isProcessing: () => running,
|
|
37126
|
-
dispose
|
|
37127
|
-
disposed = true;
|
|
37128
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
37129
|
-
}
|
|
37256
|
+
dispose
|
|
37130
37257
|
};
|
|
37131
37258
|
}
|
|
37132
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
|