@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/expo/index.cjs
CHANGED
|
@@ -12722,6 +12722,11 @@ init_logger();
|
|
|
12722
12722
|
|
|
12723
12723
|
// src/lib/db/entities/operations.ts
|
|
12724
12724
|
var import_watermelondb19 = require("@nozbe/watermelondb");
|
|
12725
|
+
async function assertCanWrite(ctx) {
|
|
12726
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
12727
|
+
throw new Error("Memory source is no longer eligible");
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12725
12730
|
function entityToStored(e) {
|
|
12726
12731
|
return {
|
|
12727
12732
|
uniqueId: e.id,
|
|
@@ -12862,6 +12867,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
12862
12867
|
let skipped = false;
|
|
12863
12868
|
let entities = [];
|
|
12864
12869
|
await ctx.database.write(async () => {
|
|
12870
|
+
await assertCanWrite(ctx);
|
|
12865
12871
|
const {
|
|
12866
12872
|
entities: byName,
|
|
12867
12873
|
operations: entityOps,
|
|
@@ -12937,6 +12943,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
12937
12943
|
let skipped = false;
|
|
12938
12944
|
let entities = [];
|
|
12939
12945
|
await ctx.database.write(async () => {
|
|
12946
|
+
await assertCanWrite(ctx);
|
|
12940
12947
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
12941
12948
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
12942
12949
|
skipped = true;
|
|
@@ -12997,6 +13004,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
12997
13004
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("memory_id", import_watermelondb19.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
12998
13005
|
if (links.length === 0) return;
|
|
12999
13006
|
await ctx.database.write(async () => {
|
|
13007
|
+
await assertCanWrite(ctx);
|
|
13000
13008
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
13001
13009
|
});
|
|
13002
13010
|
}
|
|
@@ -13005,6 +13013,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
13005
13013
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("user_id", userId)).fetch();
|
|
13006
13014
|
if (links.length === 0) return;
|
|
13007
13015
|
await ctx.database.write(async () => {
|
|
13016
|
+
await assertCanWrite(ctx);
|
|
13008
13017
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
13009
13018
|
});
|
|
13010
13019
|
}
|
|
@@ -13097,6 +13106,17 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
13097
13106
|
};
|
|
13098
13107
|
}
|
|
13099
13108
|
|
|
13109
|
+
// src/lib/db/memoryVault/sourceChunkIds.ts
|
|
13110
|
+
var MAX_SOURCE_CHUNK_IDS_BYTES = 16 << 10;
|
|
13111
|
+
var utf8 = new TextEncoder();
|
|
13112
|
+
function serializeSourceChunkIds(ids) {
|
|
13113
|
+
const sizes = ids.map((id) => utf8.encode(JSON.stringify(id)).length + 1);
|
|
13114
|
+
let total = sizes.reduce((sum, size) => sum + size, 1);
|
|
13115
|
+
let start = 0;
|
|
13116
|
+
while (total > MAX_SOURCE_CHUNK_IDS_BYTES && start < ids.length) total -= sizes[start++];
|
|
13117
|
+
return JSON.stringify(ids.slice(start));
|
|
13118
|
+
}
|
|
13119
|
+
|
|
13100
13120
|
// src/lib/db/memoryVault/types.ts
|
|
13101
13121
|
var MEMORY_KINDS = [
|
|
13102
13122
|
"display_name",
|
|
@@ -13169,6 +13189,11 @@ function visibilityConditions(requested) {
|
|
|
13169
13189
|
function isKinded(record2) {
|
|
13170
13190
|
return record2.kind !== null && record2.kind !== void 0;
|
|
13171
13191
|
}
|
|
13192
|
+
async function assertCanWrite2(ctx) {
|
|
13193
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
13194
|
+
throw new Error("Memory source is no longer eligible");
|
|
13195
|
+
}
|
|
13196
|
+
}
|
|
13172
13197
|
function assertValidKindLevel(kind, level) {
|
|
13173
13198
|
const hasKind = kind !== null && kind !== void 0;
|
|
13174
13199
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -13244,15 +13269,15 @@ async function mapInBatches(items, fn) {
|
|
|
13244
13269
|
return results;
|
|
13245
13270
|
}
|
|
13246
13271
|
function vaultMemoryToStoredRaw(memory) {
|
|
13247
|
-
let
|
|
13272
|
+
let sourceChunkIds2 = null;
|
|
13248
13273
|
if (memory.sourceChunkIds) {
|
|
13249
13274
|
try {
|
|
13250
13275
|
const parsed = JSON.parse(memory.sourceChunkIds);
|
|
13251
13276
|
if (Array.isArray(parsed)) {
|
|
13252
|
-
|
|
13277
|
+
sourceChunkIds2 = parsed.filter((s) => typeof s === "string");
|
|
13253
13278
|
}
|
|
13254
13279
|
} catch {
|
|
13255
|
-
|
|
13280
|
+
sourceChunkIds2 = null;
|
|
13256
13281
|
}
|
|
13257
13282
|
}
|
|
13258
13283
|
return {
|
|
@@ -13266,7 +13291,7 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
13266
13291
|
userId: memory.userId ?? null,
|
|
13267
13292
|
embedding: memory.embedding ?? null,
|
|
13268
13293
|
embeddingModel: memory.embeddingModel ?? null,
|
|
13269
|
-
sourceChunkIds,
|
|
13294
|
+
sourceChunkIds: sourceChunkIds2,
|
|
13270
13295
|
proofCount: memory.proofCount ?? null,
|
|
13271
13296
|
source: memory.source ?? null,
|
|
13272
13297
|
media: parseMedia(memory.media),
|
|
@@ -13315,7 +13340,7 @@ function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedK
|
|
|
13315
13340
|
record2._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
13316
13341
|
}
|
|
13317
13342
|
if (opts.sourceChunkIds !== void 0) {
|
|
13318
|
-
record2._setRaw("source_chunk_ids",
|
|
13343
|
+
record2._setRaw("source_chunk_ids", serializeSourceChunkIds(opts.sourceChunkIds));
|
|
13319
13344
|
}
|
|
13320
13345
|
record2._setRaw("proof_count", opts.proofCount ?? 1);
|
|
13321
13346
|
record2._setRaw("source", opts.source ?? "manual");
|
|
@@ -13349,8 +13374,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
13349
13374
|
ctx.embeddedWalletSigner
|
|
13350
13375
|
) : opts.content;
|
|
13351
13376
|
const created = await ctx.database.write(async () => {
|
|
13352
|
-
|
|
13353
|
-
throw new Error("Memory source is no longer eligible");
|
|
13377
|
+
await assertCanWrite2(ctx);
|
|
13354
13378
|
return ctx.vaultMemoryCollection.create(
|
|
13355
13379
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13356
13380
|
);
|
|
@@ -13369,8 +13393,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
13369
13393
|
) : opts.content;
|
|
13370
13394
|
let createdRecord = null;
|
|
13371
13395
|
await ctx.database.write(async () => {
|
|
13372
|
-
|
|
13373
|
-
throw new Error("Memory source is no longer eligible");
|
|
13396
|
+
await assertCanWrite2(ctx);
|
|
13374
13397
|
let target;
|
|
13375
13398
|
try {
|
|
13376
13399
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -13462,8 +13485,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13462
13485
|
})
|
|
13463
13486
|
);
|
|
13464
13487
|
const created = await ctx.database.write(async () => {
|
|
13465
|
-
|
|
13466
|
-
throw new Error("Memory source is no longer eligible");
|
|
13488
|
+
await assertCanWrite2(ctx);
|
|
13467
13489
|
const prepared = optionsArray.map(
|
|
13468
13490
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
13469
13491
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -13493,16 +13515,16 @@ async function getVaultMemoryOp(ctx, id) {
|
|
|
13493
13515
|
}
|
|
13494
13516
|
}
|
|
13495
13517
|
function vaultMemoryRawToStoredRaw(raw) {
|
|
13496
|
-
let
|
|
13518
|
+
let sourceChunkIds2 = null;
|
|
13497
13519
|
const rawChunks = raw.source_chunk_ids;
|
|
13498
13520
|
if (typeof rawChunks === "string" && rawChunks) {
|
|
13499
13521
|
try {
|
|
13500
13522
|
const parsed = JSON.parse(rawChunks);
|
|
13501
13523
|
if (Array.isArray(parsed)) {
|
|
13502
|
-
|
|
13524
|
+
sourceChunkIds2 = parsed.filter((s) => typeof s === "string");
|
|
13503
13525
|
}
|
|
13504
13526
|
} catch {
|
|
13505
|
-
|
|
13527
|
+
sourceChunkIds2 = null;
|
|
13506
13528
|
}
|
|
13507
13529
|
}
|
|
13508
13530
|
return {
|
|
@@ -13516,7 +13538,7 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
13516
13538
|
userId: raw.user_id ?? null,
|
|
13517
13539
|
embedding: raw.embedding ?? null,
|
|
13518
13540
|
embeddingModel: raw.embedding_model ?? null,
|
|
13519
|
-
sourceChunkIds,
|
|
13541
|
+
sourceChunkIds: sourceChunkIds2,
|
|
13520
13542
|
proofCount: raw.proof_count ?? null,
|
|
13521
13543
|
source: raw.source ?? null,
|
|
13522
13544
|
eventTimeStart: raw.event_time_start ?? null,
|
|
@@ -13768,8 +13790,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13768
13790
|
const record2 = probe;
|
|
13769
13791
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13770
13792
|
await ctx.database.write(async () => {
|
|
13771
|
-
|
|
13772
|
-
throw new Error("Memory source is no longer eligible");
|
|
13793
|
+
await assertCanWrite2(ctx);
|
|
13773
13794
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
13774
13795
|
stale = true;
|
|
13775
13796
|
return;
|
|
@@ -13813,7 +13834,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13813
13834
|
if (opts.sourceChunkIds !== void 0) {
|
|
13814
13835
|
r._setRaw(
|
|
13815
13836
|
"source_chunk_ids",
|
|
13816
|
-
|
|
13837
|
+
serializeSourceChunkIds(
|
|
13817
13838
|
opts.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observedSources, ...opts.sourceChunkIds])] : opts.sourceChunkIds
|
|
13818
13839
|
)
|
|
13819
13840
|
);
|
|
@@ -13880,6 +13901,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
13880
13901
|
let stale = false;
|
|
13881
13902
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13882
13903
|
await ctx.database.write(async (writer) => {
|
|
13904
|
+
await assertCanWrite2(ctx);
|
|
13883
13905
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13884
13906
|
stale = true;
|
|
13885
13907
|
return;
|
|
@@ -13921,6 +13943,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
13921
13943
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13922
13944
|
let cleared = false;
|
|
13923
13945
|
await ctx.database.write(async () => {
|
|
13946
|
+
await assertCanWrite2(ctx);
|
|
13924
13947
|
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
13925
13948
|
cleared = true;
|
|
13926
13949
|
await record2.update((r) => {
|
|
@@ -13944,6 +13967,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
13944
13967
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
13945
13968
|
let stale = false;
|
|
13946
13969
|
await ctx.database.write(async () => {
|
|
13970
|
+
await assertCanWrite2(ctx);
|
|
13947
13971
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13948
13972
|
stale = true;
|
|
13949
13973
|
return;
|
|
@@ -13972,6 +13996,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
13972
13996
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
13973
13997
|
let stale = false;
|
|
13974
13998
|
await ctx.database.write(async () => {
|
|
13999
|
+
await assertCanWrite2(ctx);
|
|
13975
14000
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13976
14001
|
stale = true;
|
|
13977
14002
|
return;
|
|
@@ -14009,8 +14034,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
14009
14034
|
}
|
|
14010
14035
|
let stale = false;
|
|
14011
14036
|
await ctx.database.write(async () => {
|
|
14012
|
-
|
|
14013
|
-
throw new Error("Memory source is no longer eligible");
|
|
14037
|
+
await assertCanWrite2(ctx);
|
|
14014
14038
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
14015
14039
|
stale = true;
|
|
14016
14040
|
return;
|
|
@@ -14172,6 +14196,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
14172
14196
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
14173
14197
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
14174
14198
|
await ctx.database.write(async () => {
|
|
14199
|
+
await assertCanWrite2(ctx);
|
|
14175
14200
|
const records = [];
|
|
14176
14201
|
for (const id of chunkIds) {
|
|
14177
14202
|
try {
|
|
@@ -14205,6 +14230,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14205
14230
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
14206
14231
|
try {
|
|
14207
14232
|
await ctx.database.write(async (writer) => {
|
|
14233
|
+
await assertCanWrite2(ctx);
|
|
14208
14234
|
let record2;
|
|
14209
14235
|
try {
|
|
14210
14236
|
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -14235,6 +14261,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14235
14261
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
14236
14262
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
14237
14263
|
await ctx.database.write(async () => {
|
|
14264
|
+
await assertCanWrite2(ctx);
|
|
14238
14265
|
const writes = [];
|
|
14239
14266
|
for (const id of chunkIds) {
|
|
14240
14267
|
let record2;
|
|
@@ -14267,6 +14294,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
14267
14294
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb20.Q.where("user_id", userId), import_watermelondb20.Q.where("is_deleted", false)).fetch();
|
|
14268
14295
|
if (records.length === 0) return 0;
|
|
14269
14296
|
await ctx.database.write(async () => {
|
|
14297
|
+
await assertCanWrite2(ctx);
|
|
14270
14298
|
const prepared = records.map(
|
|
14271
14299
|
(record2) => record2.prepareUpdate((r) => {
|
|
14272
14300
|
r._setRaw("is_deleted", true);
|
|
@@ -14321,6 +14349,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
14321
14349
|
let stale = false;
|
|
14322
14350
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
14323
14351
|
await ctx.database.write(async () => {
|
|
14352
|
+
await assertCanWrite2(ctx);
|
|
14324
14353
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
14325
14354
|
stale = true;
|
|
14326
14355
|
return;
|
|
@@ -14344,6 +14373,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
14344
14373
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14345
14374
|
let stale = false;
|
|
14346
14375
|
await ctx.database.write(async () => {
|
|
14376
|
+
await assertCanWrite2(ctx);
|
|
14347
14377
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14348
14378
|
stale = true;
|
|
14349
14379
|
return;
|
|
@@ -14364,6 +14394,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
14364
14394
|
const now = opts.now ?? Date.now();
|
|
14365
14395
|
let stale = false;
|
|
14366
14396
|
await ctx.database.write(async () => {
|
|
14397
|
+
await assertCanWrite2(ctx);
|
|
14367
14398
|
const archivedAt = record2.archivedAt;
|
|
14368
14399
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
14369
14400
|
stale = true;
|
|
@@ -14403,6 +14434,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
|
|
|
14403
14434
|
}
|
|
14404
14435
|
let written = false;
|
|
14405
14436
|
await ctx.database.write(async () => {
|
|
14437
|
+
await assertCanWrite2(ctx);
|
|
14406
14438
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14407
14439
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14408
14440
|
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
@@ -17939,6 +17971,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
17939
17971
|
).map((c) => c.candidate);
|
|
17940
17972
|
}
|
|
17941
17973
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
17974
|
+
const { memoryStore, signal } = options;
|
|
17975
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
17976
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
17977
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
17978
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
17979
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
17980
|
+
signal?.throwIfAborted();
|
|
17942
17981
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
17943
17982
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
17944
17983
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -17972,6 +18011,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17972
18011
|
}
|
|
17973
18012
|
});
|
|
17974
18013
|
const extractMs = Date.now() - tExtract;
|
|
18014
|
+
signal?.throwIfAborted();
|
|
17975
18015
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
17976
18016
|
const log = getLogger();
|
|
17977
18017
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -18019,16 +18059,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
18019
18059
|
const results = [];
|
|
18020
18060
|
const quarantinedInfo = [];
|
|
18021
18061
|
let failedWrites = 0;
|
|
18062
|
+
let auditRows;
|
|
18022
18063
|
const tRetain = Date.now();
|
|
18023
18064
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
18024
18065
|
try {
|
|
18066
|
+
signal?.throwIfAborted();
|
|
18025
18067
|
if (isQuarantined) {
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
|
|
18030
|
-
|
|
18031
|
-
|
|
18068
|
+
let existingId;
|
|
18069
|
+
if (memoryStore) {
|
|
18070
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
18071
|
+
scopes: [options.scope ?? "private"],
|
|
18072
|
+
includeArchived: true,
|
|
18073
|
+
includeQuarantined: true,
|
|
18074
|
+
includeSuperseded: true
|
|
18075
|
+
}));
|
|
18076
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
18077
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
18078
|
+
existingId = (await auditRows).find(
|
|
18079
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
18080
|
+
)?.uniqueId ?? null;
|
|
18081
|
+
} else {
|
|
18082
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
18083
|
+
retainCtx.vaultCtx,
|
|
18084
|
+
candidate.content,
|
|
18085
|
+
candidate.sourceMessageIds,
|
|
18086
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
18087
|
+
).catch(() => null);
|
|
18088
|
+
}
|
|
18032
18089
|
if (existingId) {
|
|
18033
18090
|
quarantinedInfo.push({
|
|
18034
18091
|
candidate,
|
|
@@ -18039,18 +18096,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
18039
18096
|
continue;
|
|
18040
18097
|
}
|
|
18041
18098
|
}
|
|
18042
|
-
const
|
|
18099
|
+
const retainOptions = {
|
|
18043
18100
|
source: "auto-extracted",
|
|
18044
18101
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
18045
18102
|
respectTombstones: true,
|
|
18046
18103
|
...options.scope !== void 0 && { scope: options.scope },
|
|
18047
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
18048
18104
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
18049
18105
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
18050
18106
|
factType: candidate.type,
|
|
18051
18107
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
18108
|
+
};
|
|
18109
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
18110
|
+
...retainOptions,
|
|
18111
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
18112
|
+
signal
|
|
18113
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
18114
|
+
...retainOptions,
|
|
18115
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
18052
18116
|
});
|
|
18053
18117
|
if (isQuarantined) {
|
|
18118
|
+
auditRows = void 0;
|
|
18054
18119
|
const info = {
|
|
18055
18120
|
candidate,
|
|
18056
18121
|
memoryId: result.memoryId,
|
|
@@ -18069,9 +18134,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
18069
18134
|
}
|
|
18070
18135
|
succeededCandidates.push(candidate);
|
|
18071
18136
|
results.push(result);
|
|
18072
|
-
if (result.action !== "suppressed" &&
|
|
18137
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
18073
18138
|
try {
|
|
18074
|
-
|
|
18139
|
+
signal?.throwIfAborted();
|
|
18140
|
+
if (memoryStore) {
|
|
18141
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
18142
|
+
unlessUserManaged: true,
|
|
18143
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
18144
|
+
signal
|
|
18145
|
+
});
|
|
18146
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
18075
18147
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
18076
18148
|
unlessTopicsUserManaged: true
|
|
18077
18149
|
});
|
|
@@ -18321,7 +18393,7 @@ function createAutoExtractor(options) {
|
|
|
18321
18393
|
};
|
|
18322
18394
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
18323
18395
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
18324
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
18396
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
18325
18397
|
getLogger().warn(
|
|
18326
18398
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
18327
18399
|
);
|
|
@@ -18366,6 +18438,8 @@ function createAutoExtractor(options) {
|
|
|
18366
18438
|
try {
|
|
18367
18439
|
const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
18368
18440
|
extract,
|
|
18441
|
+
memoryStore: options.memoryStore,
|
|
18442
|
+
signal: options.signal,
|
|
18369
18443
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
18370
18444
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
18371
18445
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -20471,6 +20545,7 @@ function createLocalMemoryStore(options) {
|
|
|
20471
20545
|
database,
|
|
20472
20546
|
entityCollection: database.get("entity"),
|
|
20473
20547
|
memoryEntityCollection: database.get("memory_entity"),
|
|
20548
|
+
canWrite: options.canWrite,
|
|
20474
20549
|
...userId !== void 0 && { userId },
|
|
20475
20550
|
...options.allowUnscopedRows !== void 0 && {
|
|
20476
20551
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -20482,10 +20557,21 @@ function createLocalMemoryStore(options) {
|
|
|
20482
20557
|
walletAddress: options.walletAddress,
|
|
20483
20558
|
signMessage: options.signMessage,
|
|
20484
20559
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
20560
|
+
canWrite: options.canWrite,
|
|
20485
20561
|
...userId !== void 0 && { userId },
|
|
20486
20562
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
20487
20563
|
entityCtx
|
|
20488
20564
|
};
|
|
20565
|
+
const assertWrite = async (writeOptions) => {
|
|
20566
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20567
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
20568
|
+
throw new Error("Memory source is no longer eligible");
|
|
20569
|
+
}
|
|
20570
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
20571
|
+
throw new Error("Memory source is no longer eligible");
|
|
20572
|
+
}
|
|
20573
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20574
|
+
};
|
|
20489
20575
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
20490
20576
|
const ownedBy = userId !== void 0 ? [import_watermelondb23.Q.where("user_id", userId)] : [];
|
|
20491
20577
|
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)];
|
|
@@ -20597,9 +20683,25 @@ function createLocalMemoryStore(options) {
|
|
|
20597
20683
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
20598
20684
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
20599
20685
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
20600
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
20686
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
20687
|
+
await assertWrite(writeOptions);
|
|
20601
20688
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb23.Q.where("id", memoryId), import_watermelondb23.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
20602
|
-
return owned > 0 ? writer.callWriter(
|
|
20689
|
+
return owned > 0 ? writer.callWriter(
|
|
20690
|
+
() => linkMemoryEntitiesOp(
|
|
20691
|
+
{
|
|
20692
|
+
...entityCtx,
|
|
20693
|
+
canWrite: async () => {
|
|
20694
|
+
await assertWrite(writeOptions);
|
|
20695
|
+
return true;
|
|
20696
|
+
}
|
|
20697
|
+
},
|
|
20698
|
+
memoryId,
|
|
20699
|
+
topics,
|
|
20700
|
+
{
|
|
20701
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
20702
|
+
}
|
|
20703
|
+
)
|
|
20704
|
+
) : [];
|
|
20603
20705
|
}),
|
|
20604
20706
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
20605
20707
|
recall: (query, recallOptions) => recall(
|
|
@@ -20609,7 +20711,17 @@ function createLocalMemoryStore(options) {
|
|
|
20609
20711
|
),
|
|
20610
20712
|
retain: (content, retainOptions) => retain(
|
|
20611
20713
|
content,
|
|
20612
|
-
{
|
|
20714
|
+
{
|
|
20715
|
+
vaultCtx: {
|
|
20716
|
+
...vaultCtx,
|
|
20717
|
+
canWrite: async () => {
|
|
20718
|
+
await assertWrite(retainOptions);
|
|
20719
|
+
return true;
|
|
20720
|
+
}
|
|
20721
|
+
},
|
|
20722
|
+
embeddingOptions: options.embeddingOptions,
|
|
20723
|
+
vaultCache
|
|
20724
|
+
},
|
|
20613
20725
|
retainOptions
|
|
20614
20726
|
),
|
|
20615
20727
|
factSource: {
|
|
@@ -20713,13 +20825,20 @@ function memoryCipher(canonical) {
|
|
|
20713
20825
|
};
|
|
20714
20826
|
}
|
|
20715
20827
|
async function reencryptMemoryField(value, canonical, fallbacks = []) {
|
|
20716
|
-
|
|
20717
|
-
|
|
20828
|
+
return memoryCipher(canonical).encrypt(
|
|
20829
|
+
await decryptMemoryField(value, [canonical, ...fallbacks])
|
|
20830
|
+
);
|
|
20831
|
+
}
|
|
20832
|
+
async function decryptMemoryField(value, rings) {
|
|
20833
|
+
if (!value.startsWith("enc:")) return value;
|
|
20718
20834
|
if (!isEncrypted(value))
|
|
20719
20835
|
throw new MemoryKeyError("Field has an encryption prefix but an invalid payload");
|
|
20720
|
-
return
|
|
20836
|
+
return decryptWith(value, rings);
|
|
20721
20837
|
}
|
|
20722
20838
|
|
|
20839
|
+
// src/lib/memory/store/remoteMigration.ts
|
|
20840
|
+
init_logger();
|
|
20841
|
+
|
|
20723
20842
|
// src/lib/memory/store/remotePersistence.ts
|
|
20724
20843
|
init_portalLlm();
|
|
20725
20844
|
var RemoteMemoryError = class extends Error {
|
|
@@ -21257,7 +21376,14 @@ function stored(row) {
|
|
|
21257
21376
|
function createRemoteMemoryPipeline(options) {
|
|
21258
21377
|
const { persistence, embeddingOptions } = options;
|
|
21259
21378
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21260
|
-
const operation = (mode, queryOptions = embeddingOptions) => {
|
|
21379
|
+
const operation = (mode, queryOptions = embeddingOptions, writeOptions) => {
|
|
21380
|
+
const signal = writeOptions?.signal;
|
|
21381
|
+
const assertWrite = async () => {
|
|
21382
|
+
signal?.throwIfAborted();
|
|
21383
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
21384
|
+
throw new Error("Memory source is no longer eligible");
|
|
21385
|
+
signal?.throwIfAborted();
|
|
21386
|
+
};
|
|
21261
21387
|
const rejectUndecryptable = (failed) => {
|
|
21262
21388
|
if (!failed.length) return;
|
|
21263
21389
|
if (mode === "retain")
|
|
@@ -21275,7 +21401,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21275
21401
|
return items.map((item) => stored(item.memory));
|
|
21276
21402
|
};
|
|
21277
21403
|
const get = async (id) => {
|
|
21278
|
-
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
21404
|
+
const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
21279
21405
|
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
21280
21406
|
snapshots.set(id, snapshot);
|
|
21281
21407
|
return stored(snapshot.memory);
|
|
@@ -21325,7 +21451,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21325
21451
|
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
21326
21452
|
}
|
|
21327
21453
|
const forceIds = [...forced];
|
|
21328
|
-
const windowOptions = (i,
|
|
21454
|
+
const windowOptions = (i, signal2) => ({
|
|
21329
21455
|
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
21330
21456
|
force_ids: i === 0 ? forceIds : [],
|
|
21331
21457
|
...search.scopes && { scopes: search.scopes },
|
|
@@ -21333,13 +21459,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21333
21459
|
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
21334
21460
|
include_archived: search.includeArchived,
|
|
21335
21461
|
embedding_model: model,
|
|
21336
|
-
...
|
|
21462
|
+
...signal2 && { signal: signal2 }
|
|
21337
21463
|
});
|
|
21338
21464
|
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
21339
21465
|
let windows;
|
|
21340
21466
|
if (mode === "retain") {
|
|
21341
21467
|
windows = await Promise.all(
|
|
21342
|
-
vectors.map(
|
|
21468
|
+
vectors.map(
|
|
21469
|
+
(embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
|
|
21470
|
+
)
|
|
21343
21471
|
);
|
|
21344
21472
|
} else {
|
|
21345
21473
|
const deadline = new AbortController();
|
|
@@ -21412,7 +21540,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21412
21540
|
embedding: storedVector(JSON.parse(input.embedding)),
|
|
21413
21541
|
embedding_model: input.embeddingModel
|
|
21414
21542
|
},
|
|
21415
|
-
source_chunk_ids:
|
|
21543
|
+
source_chunk_ids: serializeSourceChunkIds(input.sourceChunkIds ?? []),
|
|
21416
21544
|
proof_count: input.proofCount ?? 1,
|
|
21417
21545
|
source: input.source ?? "manual",
|
|
21418
21546
|
...input.eventTime && {
|
|
@@ -21427,12 +21555,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21427
21555
|
twin_opt_in: false
|
|
21428
21556
|
};
|
|
21429
21557
|
};
|
|
21430
|
-
const write = async (memory, snapshot) =>
|
|
21558
|
+
const write = async (memory, snapshot) => {
|
|
21559
|
+
await assertWrite();
|
|
21560
|
+
return remember([await persistence.put(memory, snapshot, signal)])[0];
|
|
21561
|
+
};
|
|
21431
21562
|
const port = {
|
|
21432
21563
|
prepare,
|
|
21433
21564
|
get,
|
|
21434
21565
|
getFresh: async (id) => {
|
|
21435
|
-
const current = await persistence.get(id);
|
|
21566
|
+
const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
21436
21567
|
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
21437
21568
|
},
|
|
21438
21569
|
tombstones: async (embedding2, embeddingModel, scope, folderId) => {
|
|
@@ -21443,7 +21574,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21443
21574
|
embedding_model: embeddingModel,
|
|
21444
21575
|
strict_model: true,
|
|
21445
21576
|
include_deleted: true,
|
|
21446
|
-
deleted_only: true
|
|
21577
|
+
deleted_only: true,
|
|
21578
|
+
signal
|
|
21447
21579
|
});
|
|
21448
21580
|
rejectUndecryptable(window2.failed);
|
|
21449
21581
|
return remember(window2.items);
|
|
@@ -21471,7 +21603,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21471
21603
|
const observed = sourceIds(memory.source_chunk_ids);
|
|
21472
21604
|
const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
|
|
21473
21605
|
if (patch.sourceChunkIds !== void 0)
|
|
21474
|
-
memory.source_chunk_ids =
|
|
21606
|
+
memory.source_chunk_ids = serializeSourceChunkIds(
|
|
21475
21607
|
patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
|
|
21476
21608
|
);
|
|
21477
21609
|
if (!replay) {
|
|
@@ -21499,14 +21631,18 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21499
21631
|
if (!target || !newer || id === successor) return false;
|
|
21500
21632
|
const old = snapshots.get(id);
|
|
21501
21633
|
const next = snapshots.get(successor);
|
|
21634
|
+
await assertWrite();
|
|
21502
21635
|
remember(
|
|
21503
|
-
await persistence.putMany(
|
|
21504
|
-
|
|
21505
|
-
|
|
21506
|
-
|
|
21507
|
-
|
|
21508
|
-
|
|
21509
|
-
|
|
21636
|
+
await persistence.putMany(
|
|
21637
|
+
[
|
|
21638
|
+
{
|
|
21639
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
21640
|
+
expectedVersion: old
|
|
21641
|
+
},
|
|
21642
|
+
{ memory: next.memory, expectedVersion: next }
|
|
21643
|
+
],
|
|
21644
|
+
signal
|
|
21645
|
+
)
|
|
21510
21646
|
);
|
|
21511
21647
|
return true;
|
|
21512
21648
|
},
|
|
@@ -21515,18 +21651,22 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21515
21651
|
if (!target) return { created: null, retired: false };
|
|
21516
21652
|
const snapshot = snapshots.get(targetId);
|
|
21517
21653
|
const successor = createRow(input);
|
|
21654
|
+
await assertWrite();
|
|
21518
21655
|
const rows = remember(
|
|
21519
|
-
await persistence.putMany(
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
|
|
21526
|
-
|
|
21527
|
-
|
|
21528
|
-
|
|
21529
|
-
|
|
21656
|
+
await persistence.putMany(
|
|
21657
|
+
[
|
|
21658
|
+
{ memory: successor, expectedVersion: 0 },
|
|
21659
|
+
{
|
|
21660
|
+
memory: {
|
|
21661
|
+
...snapshot.memory,
|
|
21662
|
+
superseded_by: successor.memory_id,
|
|
21663
|
+
superseded_at: Date.now()
|
|
21664
|
+
},
|
|
21665
|
+
expectedVersion: snapshot
|
|
21666
|
+
}
|
|
21667
|
+
],
|
|
21668
|
+
signal
|
|
21669
|
+
)
|
|
21530
21670
|
);
|
|
21531
21671
|
return { created: rows[0], retired: true };
|
|
21532
21672
|
}
|
|
@@ -21561,7 +21701,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21561
21701
|
factSource,
|
|
21562
21702
|
recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
|
|
21563
21703
|
retain: async (content, retainOptions) => {
|
|
21564
|
-
const { port } = operation("retain");
|
|
21704
|
+
const { port } = operation("retain", embeddingOptions, retainOptions);
|
|
21565
21705
|
return retainWithPersistence(
|
|
21566
21706
|
content,
|
|
21567
21707
|
{
|
|
@@ -21578,6 +21718,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21578
21718
|
|
|
21579
21719
|
// src/lib/memory/store/remoteMigration.ts
|
|
21580
21720
|
var IMPORT_BATCH = 50;
|
|
21721
|
+
var EMBED_BATCH = 100;
|
|
21722
|
+
var LOCAL_VECTOR_DIMS = 4096;
|
|
21581
21723
|
var VERIFY_BATCH = 1e3;
|
|
21582
21724
|
var QUERY_IDS = 1e3;
|
|
21583
21725
|
var QUERY_PAGE = 200;
|
|
@@ -21603,7 +21745,7 @@ var SHORT_FIELDS = [
|
|
|
21603
21745
|
"visibility",
|
|
21604
21746
|
"geohash"
|
|
21605
21747
|
];
|
|
21606
|
-
var
|
|
21748
|
+
var utf82 = new TextEncoder();
|
|
21607
21749
|
var METADATA_FIELDS = [
|
|
21608
21750
|
"scope",
|
|
21609
21751
|
"kind",
|
|
@@ -21654,17 +21796,34 @@ function revision(raw) {
|
|
|
21654
21796
|
last_observed_at: num(raw.last_observed_at) ?? null
|
|
21655
21797
|
};
|
|
21656
21798
|
}
|
|
21657
|
-
function embedding(raw) {
|
|
21799
|
+
function embedding(raw, model) {
|
|
21658
21800
|
const value = text13(raw.embedding);
|
|
21659
21801
|
if (!value) return void 0;
|
|
21660
21802
|
try {
|
|
21661
|
-
|
|
21803
|
+
const vector = JSON.parse(value);
|
|
21804
|
+
const stored2 = text13(raw.embedding_model);
|
|
21805
|
+
if (stored2 === void 0 ? vector.length !== LOCAL_VECTOR_DIMS : stored2 !== model)
|
|
21806
|
+
return void 0;
|
|
21807
|
+
return storedVector(vector);
|
|
21662
21808
|
} catch {
|
|
21663
21809
|
return void 0;
|
|
21664
21810
|
}
|
|
21665
21811
|
}
|
|
21812
|
+
function stringArray(value) {
|
|
21813
|
+
try {
|
|
21814
|
+
const parsed = JSON.parse(value);
|
|
21815
|
+
return Array.isArray(parsed) && parsed.every((id) => typeof id === "string") ? parsed : void 0;
|
|
21816
|
+
} catch {
|
|
21817
|
+
return void 0;
|
|
21818
|
+
}
|
|
21819
|
+
}
|
|
21820
|
+
function sourceChunkIds(raw) {
|
|
21821
|
+
const value = text13(raw.source_chunk_ids);
|
|
21822
|
+
const ids = value && stringArray(value);
|
|
21823
|
+
return ids ? serializeSourceChunkIds(ids) : value;
|
|
21824
|
+
}
|
|
21666
21825
|
function bytes(value) {
|
|
21667
|
-
return value === void 0 ? 0 :
|
|
21826
|
+
return value === void 0 ? 0 : utf82.encode(value).length;
|
|
21668
21827
|
}
|
|
21669
21828
|
function fitsNearby(row) {
|
|
21670
21829
|
return bytes(row.memory_id) <= MAX_ID_BYTES && bytes(row.content) <= MAX_CONTENT_BYTES && bytes(row.kind_value) <= MAX_CONTENT_BYTES && TEXT_FIELDS.every((field10) => bytes(row[field10]) <= MAX_TEXT_BYTES) && SHORT_FIELDS.every((field10) => bytes(row[field10]) <= MAX_SHORT_BYTES);
|
|
@@ -21673,16 +21832,16 @@ function invalid(raw) {
|
|
|
21673
21832
|
const id = raw.id;
|
|
21674
21833
|
return typeof id !== "string" || id === "" || bytes(id) > MAX_ID_BYTES || !text13(raw.scope) || (num(raw.created_at) ?? 0) <= 0 || (num(raw.updated_at) ?? 0) <= 0;
|
|
21675
21834
|
}
|
|
21676
|
-
function metadata(raw) {
|
|
21677
|
-
const vector = embedding(raw);
|
|
21835
|
+
function metadata(raw, model) {
|
|
21836
|
+
const vector = embedding(raw, model);
|
|
21678
21837
|
return {
|
|
21679
21838
|
scope: raw.scope,
|
|
21680
21839
|
kind: text13(raw.kind),
|
|
21681
21840
|
level: text13(raw.level),
|
|
21682
21841
|
folder_id: text13(raw.folder_id),
|
|
21683
21842
|
is_deleted: bool(raw.is_deleted) ?? false,
|
|
21684
|
-
...vector && { embedding: vector, embedding_model:
|
|
21685
|
-
source_chunk_ids:
|
|
21843
|
+
...vector && { embedding: vector, embedding_model: model },
|
|
21844
|
+
source_chunk_ids: sourceChunkIds(raw),
|
|
21686
21845
|
proof_count: num(raw.proof_count),
|
|
21687
21846
|
source: text13(raw.source),
|
|
21688
21847
|
event_time_start: num(raw.event_time_start),
|
|
@@ -21711,30 +21870,63 @@ function defined(value) {
|
|
|
21711
21870
|
Object.entries(value).filter(([, field10]) => field10 !== void 0)
|
|
21712
21871
|
);
|
|
21713
21872
|
}
|
|
21714
|
-
async function
|
|
21715
|
-
const
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
21720
|
-
|
|
21721
|
-
|
|
21873
|
+
async function prepareRow(raw, canonical, rings, model, updatedAt) {
|
|
21874
|
+
const deleted = bool(raw.is_deleted) ?? false;
|
|
21875
|
+
const { encrypt } = memoryCipher(canonical);
|
|
21876
|
+
const localKindValue = text13(raw.kind_value);
|
|
21877
|
+
let plaintext;
|
|
21878
|
+
let kindValue;
|
|
21879
|
+
try {
|
|
21880
|
+
plaintext = await decryptMemoryField(typeof raw.content === "string" ? raw.content : "", rings);
|
|
21881
|
+
kindValue = localKindValue && await decryptMemoryField(localKindValue, rings);
|
|
21882
|
+
} catch (error) {
|
|
21883
|
+
if (!deleted || !(error instanceof MemoryKeyError)) throw error;
|
|
21884
|
+
plaintext = void 0;
|
|
21885
|
+
kindValue = void 0;
|
|
21886
|
+
}
|
|
21722
21887
|
const row = {
|
|
21723
|
-
...defined({
|
|
21888
|
+
...defined({
|
|
21889
|
+
...metadata(raw, model),
|
|
21890
|
+
kind_value: kindValue === void 0 ? void 0 : await encrypt(kindValue)
|
|
21891
|
+
}),
|
|
21724
21892
|
memory_id: raw.id,
|
|
21725
|
-
content,
|
|
21893
|
+
content: await encrypt(plaintext ?? ""),
|
|
21726
21894
|
scope: raw.scope,
|
|
21727
21895
|
created_at: raw.created_at,
|
|
21728
21896
|
updated_at: updatedAt,
|
|
21729
|
-
is_deleted:
|
|
21897
|
+
is_deleted: deleted
|
|
21730
21898
|
};
|
|
21731
|
-
return
|
|
21899
|
+
return { row, plaintext };
|
|
21900
|
+
}
|
|
21901
|
+
async function embedMissing(prepared, options, model, signal) {
|
|
21902
|
+
const needed = prepared.filter((p) => !p.row.embedding && p.plaintext);
|
|
21903
|
+
for (const batch of chunks(needed, EMBED_BATCH)) {
|
|
21904
|
+
if (signal?.aborted) throw aborted(signal);
|
|
21905
|
+
try {
|
|
21906
|
+
const vectors = await generateEmbeddings(
|
|
21907
|
+
batch.map((p) => p.plaintext),
|
|
21908
|
+
{ ...options, taskType: "memory_retain_embed" }
|
|
21909
|
+
);
|
|
21910
|
+
if (vectors.length !== batch.length) throw new Error("Incomplete migration embeddings");
|
|
21911
|
+
const stored2 = vectors.map(storedVector);
|
|
21912
|
+
batch.forEach((p, i) => {
|
|
21913
|
+
p.row.embedding = stored2[i];
|
|
21914
|
+
p.row.embedding_model = model;
|
|
21915
|
+
});
|
|
21916
|
+
} catch (error) {
|
|
21917
|
+
getLogger().warn(
|
|
21918
|
+
`[memory/migration] Uploading ${batch.length} row(s) without a vector: embedding failed`,
|
|
21919
|
+
error
|
|
21920
|
+
);
|
|
21921
|
+
}
|
|
21922
|
+
}
|
|
21732
21923
|
}
|
|
21733
|
-
function sameMetadata(local, remote) {
|
|
21734
|
-
const mine = metadata(local);
|
|
21924
|
+
function sameMetadata(local, remote, model) {
|
|
21925
|
+
const mine = metadata(local, model);
|
|
21735
21926
|
return METADATA_FIELDS.every((field10) => {
|
|
21736
21927
|
const a = mine[field10] ?? null;
|
|
21737
21928
|
const b = remote[field10] ?? null;
|
|
21929
|
+
if (field10 === "embedding_model" && a === null) return true;
|
|
21738
21930
|
if (field10 === "visibility") return (a ?? "private") === (b ?? "private");
|
|
21739
21931
|
if (field10 === "is_deleted" || field10 === "topics_user_managed" || field10 === "twin_opt_in")
|
|
21740
21932
|
return (a ?? false) === (b ?? false);
|
|
@@ -21830,7 +22022,8 @@ async function backfillTopics(ctx) {
|
|
|
21830
22022
|
}
|
|
21831
22023
|
async function migrateMemoriesToRemote(options) {
|
|
21832
22024
|
const { canonical, signal } = options;
|
|
21833
|
-
const
|
|
22025
|
+
const rings = [canonical, ...options.fallbacks ?? []];
|
|
22026
|
+
const model = options.embeddingOptions?.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21834
22027
|
const request = createNearbyRequest(options);
|
|
21835
22028
|
const account = await request("/account", {}, signal);
|
|
21836
22029
|
if (typeof account.key_id === "string" && account.key_id !== canonical.keyId)
|
|
@@ -21841,8 +22034,13 @@ async function migrateMemoriesToRemote(options) {
|
|
|
21841
22034
|
);
|
|
21842
22035
|
const active = account.state === "active";
|
|
21843
22036
|
let claimed = account.key_id === canonical.keyId;
|
|
22037
|
+
if (!active) await createDecaySweeper({ vaultCtx: options.vaultCtx }).runSweep();
|
|
21844
22038
|
await backfillTopics(options.vaultCtx);
|
|
21845
22039
|
const skipped = /* @__PURE__ */ new Map();
|
|
22040
|
+
const reembedded = /* @__PURE__ */ new Set();
|
|
22041
|
+
const unembedded = /* @__PURE__ */ new Set();
|
|
22042
|
+
const placeholders = /* @__PURE__ */ new Set();
|
|
22043
|
+
const truncated = /* @__PURE__ */ new Set();
|
|
21846
22044
|
let imported = 0;
|
|
21847
22045
|
for (let pass = 0; ; pass++) {
|
|
21848
22046
|
const rows = await getAllVaultMemoryRowsOp(options.vaultCtx);
|
|
@@ -21858,9 +22056,10 @@ async function migrateMemoriesToRemote(options) {
|
|
|
21858
22056
|
candidates.map((raw) => raw.id),
|
|
21859
22057
|
signal
|
|
21860
22058
|
);
|
|
22059
|
+
const needsVector = (raw, server) => !!options.embeddingOptions && !embedding(raw, model) && server.embedding_model !== model;
|
|
21861
22060
|
for (const raw of candidates) {
|
|
21862
22061
|
const server = remote.get(raw.id);
|
|
21863
|
-
if (server && server.updated_at === raw.updated_at && !sameMetadata(raw, server))
|
|
22062
|
+
if (server && server.updated_at === raw.updated_at && (!sameMetadata(raw, server, model) || needsVector(raw, server)))
|
|
21864
22063
|
pending.set(raw.id, raw.updated_at + 1);
|
|
21865
22064
|
}
|
|
21866
22065
|
}
|
|
@@ -21869,7 +22068,11 @@ async function migrateMemoriesToRemote(options) {
|
|
|
21869
22068
|
state,
|
|
21870
22069
|
total: rows.length,
|
|
21871
22070
|
imported,
|
|
21872
|
-
skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason }))
|
|
22071
|
+
skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason })),
|
|
22072
|
+
reembedded: reembedded.size,
|
|
22073
|
+
unembedded: unembedded.size,
|
|
22074
|
+
placeholderTombstones: placeholders.size,
|
|
22075
|
+
truncatedSourceChunkIds: truncated.size
|
|
21873
22076
|
});
|
|
21874
22077
|
if (skipped.size > 0 && !options.allowSkipped) return result("migrating");
|
|
21875
22078
|
if (!claimed) await importBatch(request, canonical.keyId, [], signal);
|
|
@@ -21887,19 +22090,35 @@ async function migrateMemoriesToRemote(options) {
|
|
|
21887
22090
|
409,
|
|
21888
22091
|
"migration_incomplete"
|
|
21889
22092
|
);
|
|
21890
|
-
const
|
|
22093
|
+
const prepared = [];
|
|
21891
22094
|
for (const raw of candidates) {
|
|
21892
22095
|
const updatedAt = pending.get(raw.id);
|
|
21893
22096
|
if (updatedAt === void 0) continue;
|
|
21894
22097
|
try {
|
|
21895
|
-
|
|
21896
|
-
if (row) upload.push(row);
|
|
21897
|
-
else skipped.set(raw.id, "invalid");
|
|
22098
|
+
prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
|
|
21898
22099
|
} catch (error) {
|
|
21899
22100
|
if (!(error instanceof MemoryKeyError)) throw error;
|
|
21900
22101
|
skipped.set(raw.id, "unreadable");
|
|
21901
22102
|
}
|
|
21902
22103
|
}
|
|
22104
|
+
const usable = new Set(prepared.filter((p) => p.row.embedding).map((p) => p.row.memory_id));
|
|
22105
|
+
if (options.embeddingOptions)
|
|
22106
|
+
await embedMissing(prepared, options.embeddingOptions, model, signal);
|
|
22107
|
+
const local = new Map(candidates.map((raw) => [raw.id, raw]));
|
|
22108
|
+
const upload = [];
|
|
22109
|
+
for (const { row, plaintext } of prepared) {
|
|
22110
|
+
const id = row.memory_id;
|
|
22111
|
+
if (!fitsNearby(row)) {
|
|
22112
|
+
skipped.set(id, "invalid");
|
|
22113
|
+
continue;
|
|
22114
|
+
}
|
|
22115
|
+
upload.push(row);
|
|
22116
|
+
const track = (set, on) => on ? set.add(id) : set.delete(id);
|
|
22117
|
+
track(reembedded, !!row.embedding && !usable.has(id));
|
|
22118
|
+
track(unembedded, !row.embedding);
|
|
22119
|
+
track(placeholders, plaintext === void 0);
|
|
22120
|
+
track(truncated, row.source_chunk_ids !== text13(local.get(id).source_chunk_ids));
|
|
22121
|
+
}
|
|
21903
22122
|
let sent = 0;
|
|
21904
22123
|
options.onProgress?.({ imported: sent, toImport: upload.length });
|
|
21905
22124
|
for (const batch of chunks(upload, IMPORT_BATCH)) {
|
|
@@ -22144,16 +22363,21 @@ function createRemoteMemoryStore(options) {
|
|
|
22144
22363
|
const record2 = await persistence.get(id);
|
|
22145
22364
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
22146
22365
|
};
|
|
22147
|
-
const mutateLocked = async (id, change, edit) => {
|
|
22148
|
-
|
|
22366
|
+
const mutateLocked = async (id, change, edit, writeOptions) => {
|
|
22367
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22368
|
+
const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
|
|
22149
22369
|
if (!record2) return null;
|
|
22370
|
+
if (record2.memory.is_deleted) return null;
|
|
22371
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
22372
|
+
throw new Error("Memory source is no longer eligible");
|
|
22373
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22150
22374
|
const next = edit(structuredClone(record2.memory));
|
|
22151
22375
|
if (!next) return null;
|
|
22152
|
-
const saved = await persistence.put(next, record2);
|
|
22376
|
+
const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
|
|
22153
22377
|
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
22154
22378
|
return saved;
|
|
22155
22379
|
};
|
|
22156
|
-
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
22380
|
+
const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
|
|
22157
22381
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
22158
22382
|
const mutateMany = async (ids, change, edit) => {
|
|
22159
22383
|
const saved = /* @__PURE__ */ new Map();
|
|
@@ -22666,13 +22890,21 @@ function createRemoteMemoryStore(options) {
|
|
|
22666
22890
|
}))
|
|
22667
22891
|
);
|
|
22668
22892
|
},
|
|
22669
|
-
addTopics: async (memoryId, topics) => {
|
|
22893
|
+
addTopics: async (memoryId, topics, writeOptions) => {
|
|
22670
22894
|
const added = await withKnownKinds(topicInputs(topics, "auto"));
|
|
22671
|
-
const saved = await mutate(
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
22675
|
-
|
|
22895
|
+
const saved = await mutate(
|
|
22896
|
+
memoryId,
|
|
22897
|
+
"edit",
|
|
22898
|
+
(memory) => {
|
|
22899
|
+
if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
|
|
22900
|
+
return {
|
|
22901
|
+
...memory,
|
|
22902
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
22903
|
+
topics_updated_at: Date.now()
|
|
22904
|
+
};
|
|
22905
|
+
},
|
|
22906
|
+
writeOptions
|
|
22907
|
+
);
|
|
22676
22908
|
if (!saved) return [];
|
|
22677
22909
|
const now = /* @__PURE__ */ new Date();
|
|
22678
22910
|
return mergeTopics([], added).map(
|
|
@@ -23525,6 +23757,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23525
23757
|
};
|
|
23526
23758
|
const folderId = options.folderId ?? null;
|
|
23527
23759
|
let disposed = false;
|
|
23760
|
+
let activeBatch = null;
|
|
23528
23761
|
let running = false;
|
|
23529
23762
|
let wakeRequested = false;
|
|
23530
23763
|
let timer;
|
|
@@ -23561,14 +23794,18 @@ function createDurableAutoExtractor(options) {
|
|
|
23561
23794
|
}, delay);
|
|
23562
23795
|
}
|
|
23563
23796
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
23797
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
23564
23798
|
let watchdog;
|
|
23565
23799
|
let cancelled = false;
|
|
23800
|
+
const controller = new AbortController();
|
|
23801
|
+
activeBatch = controller;
|
|
23566
23802
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
23567
23803
|
try {
|
|
23568
23804
|
return await Promise.race([
|
|
23569
23805
|
new Promise((resolve, reject) => {
|
|
23570
23806
|
const worker = createAutoExtractor({
|
|
23571
23807
|
...options,
|
|
23808
|
+
signal: controller.signal,
|
|
23572
23809
|
retainCtx: {
|
|
23573
23810
|
...options.retainCtx,
|
|
23574
23811
|
vaultCtx: {
|
|
@@ -23597,6 +23834,8 @@ function createDurableAutoExtractor(options) {
|
|
|
23597
23834
|
]);
|
|
23598
23835
|
} finally {
|
|
23599
23836
|
cancelled = true;
|
|
23837
|
+
controller.abort();
|
|
23838
|
+
if (activeBatch === controller) activeBatch = null;
|
|
23600
23839
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
23601
23840
|
}
|
|
23602
23841
|
}
|
|
@@ -23608,6 +23847,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23608
23847
|
for (const message of loaded)
|
|
23609
23848
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
23610
23849
|
await database.write(async () => {
|
|
23850
|
+
if (disposed) return;
|
|
23611
23851
|
const current = idsOf(job);
|
|
23612
23852
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
23613
23853
|
if (!acknowledged.length) return;
|
|
@@ -23780,6 +24020,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23780
24020
|
jobScope,
|
|
23781
24021
|
jobFolderId
|
|
23782
24022
|
);
|
|
24023
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
23783
24024
|
options.onTurnComplete?.(result);
|
|
23784
24025
|
return result;
|
|
23785
24026
|
};
|
|
@@ -23816,6 +24057,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23816
24057
|
);
|
|
23817
24058
|
scheduleAfterSuccess = true;
|
|
23818
24059
|
} catch (error) {
|
|
24060
|
+
if (disposed) break;
|
|
23819
24061
|
attempts.set(job.id, attempted + 1);
|
|
23820
24062
|
retry = true;
|
|
23821
24063
|
reportError(error, conversationId);
|
|
@@ -23838,6 +24080,14 @@ function createDurableAutoExtractor(options) {
|
|
|
23838
24080
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
23839
24081
|
}
|
|
23840
24082
|
}
|
|
24083
|
+
function dispose() {
|
|
24084
|
+
disposed = true;
|
|
24085
|
+
activeBatch?.abort(options.signal?.reason);
|
|
24086
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
24087
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
24088
|
+
}
|
|
24089
|
+
if (options.signal?.aborted) dispose();
|
|
24090
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
23841
24091
|
schedule(0);
|
|
23842
24092
|
return {
|
|
23843
24093
|
processTurn(messages, conversationId) {
|
|
@@ -23917,10 +24167,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23917
24167
|
return true;
|
|
23918
24168
|
},
|
|
23919
24169
|
isProcessing: () => running,
|
|
23920
|
-
dispose
|
|
23921
|
-
disposed = true;
|
|
23922
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
23923
|
-
}
|
|
24170
|
+
dispose
|
|
23924
24171
|
};
|
|
23925
24172
|
}
|
|
23926
24173
|
|
|
@@ -27192,6 +27439,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
|
|
|
27192
27439
|
var NO_CONVERSATION_KEY = "__no_conversation__";
|
|
27193
27440
|
var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
|
|
27194
27441
|
var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
|
|
27442
|
+
var MEMORY_STORE_NOT_READY = "Memory store is not ready";
|
|
27195
27443
|
var conversationRedactors = /* @__PURE__ */ new Map();
|
|
27196
27444
|
var clientToolFilterCache = /* @__PURE__ */ new Map();
|
|
27197
27445
|
function getConversationRedactor(conversationId, nerDetector) {
|
|
@@ -27336,7 +27584,7 @@ function useChatStorage(options) {
|
|
|
27336
27584
|
[resolvedPiiRedaction]
|
|
27337
27585
|
);
|
|
27338
27586
|
const maskEmbeddingInput = isPiiRedactor(resolvedPiiRedaction) ? maskForEmbedding : void 0;
|
|
27339
|
-
const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
27587
|
+
const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
27340
27588
|
const messagesCollection = (0, import_react5.useMemo)(() => database.get("history"), [database]);
|
|
27341
27589
|
const conversationsCollection = (0, import_react5.useMemo)(
|
|
27342
27590
|
() => database.get("conversations"),
|
|
@@ -27585,6 +27833,7 @@ function useChatStorage(options) {
|
|
|
27585
27833
|
}, [vaultEmbeddingCache]);
|
|
27586
27834
|
const retainVaultMemory = (0, import_react5.useCallback)(
|
|
27587
27835
|
async (input) => {
|
|
27836
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27588
27837
|
if (memoryStore) {
|
|
27589
27838
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
27590
27839
|
if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -27630,6 +27879,7 @@ function useChatStorage(options) {
|
|
|
27630
27879
|
);
|
|
27631
27880
|
const createMemoryVaultTool2 = (0, import_react5.useCallback)(
|
|
27632
27881
|
(options2) => {
|
|
27882
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27633
27883
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
27634
27884
|
return createMemoryVaultTool(
|
|
27635
27885
|
memoryStore ?? vaultCtx,
|
|
@@ -27640,6 +27890,7 @@ function useChatStorage(options) {
|
|
|
27640
27890
|
);
|
|
27641
27891
|
const createRecallTool2 = (0, import_react5.useCallback)(
|
|
27642
27892
|
(toolOptions, callbacks) => {
|
|
27893
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27643
27894
|
if (!getToken && !memoryStore) {
|
|
27644
27895
|
throw new Error("getToken is required for recall tool");
|
|
27645
27896
|
}
|
|
@@ -27685,7 +27936,7 @@ function useChatStorage(options) {
|
|
|
27685
27936
|
);
|
|
27686
27937
|
const recallFn = (0, import_react5.useCallback)(
|
|
27687
27938
|
async (query, options2) => {
|
|
27688
|
-
if (!getToken && !memoryStore) {
|
|
27939
|
+
if (memoryStore === null || !getToken && !memoryStore) {
|
|
27689
27940
|
return {
|
|
27690
27941
|
memories: [],
|
|
27691
27942
|
usedBudget: options2?.budget ?? "low",
|
|
@@ -27734,6 +27985,7 @@ function useChatStorage(options) {
|
|
|
27734
27985
|
);
|
|
27735
27986
|
const getVaultMemories = (0, import_react5.useCallback)(
|
|
27736
27987
|
(options2) => {
|
|
27988
|
+
if (memoryStore === null) return Promise.resolve([]);
|
|
27737
27989
|
if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
|
|
27738
27990
|
const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
|
|
27739
27991
|
if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -27744,7 +27996,8 @@ function useChatStorage(options) {
|
|
|
27744
27996
|
[vaultCtx, memoryStore]
|
|
27745
27997
|
);
|
|
27746
27998
|
const deleteVaultMemory = (0, import_react5.useCallback)(
|
|
27747
|
-
(id) => {
|
|
27999
|
+
async (id) => {
|
|
28000
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27748
28001
|
return memoryStore ? memoryStore.delete(id) : deleteVaultMemoryOp(vaultCtx, id);
|
|
27749
28002
|
},
|
|
27750
28003
|
[vaultCtx, memoryStore]
|