@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.mjs
CHANGED
|
@@ -11131,6 +11131,11 @@ import { Q as Q5 } from "@nozbe/watermelondb";
|
|
|
11131
11131
|
|
|
11132
11132
|
// src/lib/db/entities/operations.ts
|
|
11133
11133
|
import { Q as Q4 } from "@nozbe/watermelondb";
|
|
11134
|
+
async function assertCanWrite(ctx) {
|
|
11135
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
11136
|
+
throw new Error("Memory source is no longer eligible");
|
|
11137
|
+
}
|
|
11138
|
+
}
|
|
11134
11139
|
function entityToStored(e) {
|
|
11135
11140
|
return {
|
|
11136
11141
|
uniqueId: e.id,
|
|
@@ -11271,6 +11276,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
11271
11276
|
let skipped = false;
|
|
11272
11277
|
let entities = [];
|
|
11273
11278
|
await ctx.database.write(async () => {
|
|
11279
|
+
await assertCanWrite(ctx);
|
|
11274
11280
|
const {
|
|
11275
11281
|
entities: byName,
|
|
11276
11282
|
operations: entityOps,
|
|
@@ -11346,6 +11352,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
11346
11352
|
let skipped = false;
|
|
11347
11353
|
let entities = [];
|
|
11348
11354
|
await ctx.database.write(async () => {
|
|
11355
|
+
await assertCanWrite(ctx);
|
|
11349
11356
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
11350
11357
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
11351
11358
|
skipped = true;
|
|
@@ -11406,6 +11413,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
11406
11413
|
const links = await ctx.memoryEntityCollection.query(Q4.where("memory_id", Q4.oneOf(Array.from(memoryIds)))).fetch();
|
|
11407
11414
|
if (links.length === 0) return;
|
|
11408
11415
|
await ctx.database.write(async () => {
|
|
11416
|
+
await assertCanWrite(ctx);
|
|
11409
11417
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
11410
11418
|
});
|
|
11411
11419
|
}
|
|
@@ -11414,6 +11422,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
11414
11422
|
const links = await ctx.memoryEntityCollection.query(Q4.where("user_id", userId)).fetch();
|
|
11415
11423
|
if (links.length === 0) return;
|
|
11416
11424
|
await ctx.database.write(async () => {
|
|
11425
|
+
await assertCanWrite(ctx);
|
|
11417
11426
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
11418
11427
|
});
|
|
11419
11428
|
}
|
|
@@ -11505,6 +11514,17 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
|
|
|
11505
11514
|
};
|
|
11506
11515
|
}
|
|
11507
11516
|
|
|
11517
|
+
// src/lib/db/memoryVault/sourceChunkIds.ts
|
|
11518
|
+
var MAX_SOURCE_CHUNK_IDS_BYTES = 16 << 10;
|
|
11519
|
+
var utf8 = new TextEncoder();
|
|
11520
|
+
function serializeSourceChunkIds(ids) {
|
|
11521
|
+
const sizes = ids.map((id) => utf8.encode(JSON.stringify(id)).length + 1);
|
|
11522
|
+
let total = sizes.reduce((sum, size) => sum + size, 1);
|
|
11523
|
+
let start = 0;
|
|
11524
|
+
while (total > MAX_SOURCE_CHUNK_IDS_BYTES && start < ids.length) total -= sizes[start++];
|
|
11525
|
+
return JSON.stringify(ids.slice(start));
|
|
11526
|
+
}
|
|
11527
|
+
|
|
11508
11528
|
// src/lib/db/memoryVault/types.ts
|
|
11509
11529
|
var MEMORY_KINDS = [
|
|
11510
11530
|
"display_name",
|
|
@@ -11577,6 +11597,11 @@ function visibilityConditions(requested) {
|
|
|
11577
11597
|
function isKinded(record2) {
|
|
11578
11598
|
return record2.kind !== null && record2.kind !== void 0;
|
|
11579
11599
|
}
|
|
11600
|
+
async function assertCanWrite2(ctx) {
|
|
11601
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
11602
|
+
throw new Error("Memory source is no longer eligible");
|
|
11603
|
+
}
|
|
11604
|
+
}
|
|
11580
11605
|
function assertValidKindLevel(kind, level) {
|
|
11581
11606
|
const hasKind = kind !== null && kind !== void 0;
|
|
11582
11607
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -11652,15 +11677,15 @@ async function mapInBatches(items, fn) {
|
|
|
11652
11677
|
return results;
|
|
11653
11678
|
}
|
|
11654
11679
|
function vaultMemoryToStoredRaw(memory) {
|
|
11655
|
-
let
|
|
11680
|
+
let sourceChunkIds2 = null;
|
|
11656
11681
|
if (memory.sourceChunkIds) {
|
|
11657
11682
|
try {
|
|
11658
11683
|
const parsed = JSON.parse(memory.sourceChunkIds);
|
|
11659
11684
|
if (Array.isArray(parsed)) {
|
|
11660
|
-
|
|
11685
|
+
sourceChunkIds2 = parsed.filter((s) => typeof s === "string");
|
|
11661
11686
|
}
|
|
11662
11687
|
} catch {
|
|
11663
|
-
|
|
11688
|
+
sourceChunkIds2 = null;
|
|
11664
11689
|
}
|
|
11665
11690
|
}
|
|
11666
11691
|
return {
|
|
@@ -11674,7 +11699,7 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
11674
11699
|
userId: memory.userId ?? null,
|
|
11675
11700
|
embedding: memory.embedding ?? null,
|
|
11676
11701
|
embeddingModel: memory.embeddingModel ?? null,
|
|
11677
|
-
sourceChunkIds,
|
|
11702
|
+
sourceChunkIds: sourceChunkIds2,
|
|
11678
11703
|
proofCount: memory.proofCount ?? null,
|
|
11679
11704
|
source: memory.source ?? null,
|
|
11680
11705
|
media: parseMedia(memory.media),
|
|
@@ -11723,7 +11748,7 @@ function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedK
|
|
|
11723
11748
|
record2._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
11724
11749
|
}
|
|
11725
11750
|
if (opts.sourceChunkIds !== void 0) {
|
|
11726
|
-
record2._setRaw("source_chunk_ids",
|
|
11751
|
+
record2._setRaw("source_chunk_ids", serializeSourceChunkIds(opts.sourceChunkIds));
|
|
11727
11752
|
}
|
|
11728
11753
|
record2._setRaw("proof_count", opts.proofCount ?? 1);
|
|
11729
11754
|
record2._setRaw("source", opts.source ?? "manual");
|
|
@@ -11757,8 +11782,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
11757
11782
|
ctx.embeddedWalletSigner
|
|
11758
11783
|
) : opts.content;
|
|
11759
11784
|
const created = await ctx.database.write(async () => {
|
|
11760
|
-
|
|
11761
|
-
throw new Error("Memory source is no longer eligible");
|
|
11785
|
+
await assertCanWrite2(ctx);
|
|
11762
11786
|
return ctx.vaultMemoryCollection.create(
|
|
11763
11787
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
11764
11788
|
);
|
|
@@ -11777,8 +11801,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
11777
11801
|
) : opts.content;
|
|
11778
11802
|
let createdRecord = null;
|
|
11779
11803
|
await ctx.database.write(async () => {
|
|
11780
|
-
|
|
11781
|
-
throw new Error("Memory source is no longer eligible");
|
|
11804
|
+
await assertCanWrite2(ctx);
|
|
11782
11805
|
let target;
|
|
11783
11806
|
try {
|
|
11784
11807
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -11870,8 +11893,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
11870
11893
|
})
|
|
11871
11894
|
);
|
|
11872
11895
|
const created = await ctx.database.write(async () => {
|
|
11873
|
-
|
|
11874
|
-
throw new Error("Memory source is no longer eligible");
|
|
11896
|
+
await assertCanWrite2(ctx);
|
|
11875
11897
|
const prepared = optionsArray.map(
|
|
11876
11898
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
11877
11899
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -11901,16 +11923,16 @@ async function getVaultMemoryOp(ctx, id) {
|
|
|
11901
11923
|
}
|
|
11902
11924
|
}
|
|
11903
11925
|
function vaultMemoryRawToStoredRaw(raw) {
|
|
11904
|
-
let
|
|
11926
|
+
let sourceChunkIds2 = null;
|
|
11905
11927
|
const rawChunks = raw.source_chunk_ids;
|
|
11906
11928
|
if (typeof rawChunks === "string" && rawChunks) {
|
|
11907
11929
|
try {
|
|
11908
11930
|
const parsed = JSON.parse(rawChunks);
|
|
11909
11931
|
if (Array.isArray(parsed)) {
|
|
11910
|
-
|
|
11932
|
+
sourceChunkIds2 = parsed.filter((s) => typeof s === "string");
|
|
11911
11933
|
}
|
|
11912
11934
|
} catch {
|
|
11913
|
-
|
|
11935
|
+
sourceChunkIds2 = null;
|
|
11914
11936
|
}
|
|
11915
11937
|
}
|
|
11916
11938
|
return {
|
|
@@ -11924,7 +11946,7 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
11924
11946
|
userId: raw.user_id ?? null,
|
|
11925
11947
|
embedding: raw.embedding ?? null,
|
|
11926
11948
|
embeddingModel: raw.embedding_model ?? null,
|
|
11927
|
-
sourceChunkIds,
|
|
11949
|
+
sourceChunkIds: sourceChunkIds2,
|
|
11928
11950
|
proofCount: raw.proof_count ?? null,
|
|
11929
11951
|
source: raw.source ?? null,
|
|
11930
11952
|
eventTimeStart: raw.event_time_start ?? null,
|
|
@@ -12176,8 +12198,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
12176
12198
|
const record2 = probe;
|
|
12177
12199
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12178
12200
|
await ctx.database.write(async () => {
|
|
12179
|
-
|
|
12180
|
-
throw new Error("Memory source is no longer eligible");
|
|
12201
|
+
await assertCanWrite2(ctx);
|
|
12181
12202
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
12182
12203
|
stale = true;
|
|
12183
12204
|
return;
|
|
@@ -12221,7 +12242,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
12221
12242
|
if (opts.sourceChunkIds !== void 0) {
|
|
12222
12243
|
r._setRaw(
|
|
12223
12244
|
"source_chunk_ids",
|
|
12224
|
-
|
|
12245
|
+
serializeSourceChunkIds(
|
|
12225
12246
|
opts.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observedSources, ...opts.sourceChunkIds])] : opts.sourceChunkIds
|
|
12226
12247
|
)
|
|
12227
12248
|
);
|
|
@@ -12288,6 +12309,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
12288
12309
|
let stale = false;
|
|
12289
12310
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12290
12311
|
await ctx.database.write(async (writer) => {
|
|
12312
|
+
await assertCanWrite2(ctx);
|
|
12291
12313
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12292
12314
|
stale = true;
|
|
12293
12315
|
return;
|
|
@@ -12329,6 +12351,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
12329
12351
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12330
12352
|
let cleared = false;
|
|
12331
12353
|
await ctx.database.write(async () => {
|
|
12354
|
+
await assertCanWrite2(ctx);
|
|
12332
12355
|
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
12333
12356
|
cleared = true;
|
|
12334
12357
|
await record2.update((r) => {
|
|
@@ -12352,6 +12375,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
12352
12375
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
12353
12376
|
let stale = false;
|
|
12354
12377
|
await ctx.database.write(async () => {
|
|
12378
|
+
await assertCanWrite2(ctx);
|
|
12355
12379
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12356
12380
|
stale = true;
|
|
12357
12381
|
return;
|
|
@@ -12380,6 +12404,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
12380
12404
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
12381
12405
|
let stale = false;
|
|
12382
12406
|
await ctx.database.write(async () => {
|
|
12407
|
+
await assertCanWrite2(ctx);
|
|
12383
12408
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12384
12409
|
stale = true;
|
|
12385
12410
|
return;
|
|
@@ -12417,8 +12442,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
12417
12442
|
}
|
|
12418
12443
|
let stale = false;
|
|
12419
12444
|
await ctx.database.write(async () => {
|
|
12420
|
-
|
|
12421
|
-
throw new Error("Memory source is no longer eligible");
|
|
12445
|
+
await assertCanWrite2(ctx);
|
|
12422
12446
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
12423
12447
|
stale = true;
|
|
12424
12448
|
return;
|
|
@@ -12580,6 +12604,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
12580
12604
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
12581
12605
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
12582
12606
|
await ctx.database.write(async () => {
|
|
12607
|
+
await assertCanWrite2(ctx);
|
|
12583
12608
|
const records = [];
|
|
12584
12609
|
for (const id of chunkIds) {
|
|
12585
12610
|
try {
|
|
@@ -12613,6 +12638,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
12613
12638
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
12614
12639
|
try {
|
|
12615
12640
|
await ctx.database.write(async (writer) => {
|
|
12641
|
+
await assertCanWrite2(ctx);
|
|
12616
12642
|
let record2;
|
|
12617
12643
|
try {
|
|
12618
12644
|
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -12643,6 +12669,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
12643
12669
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
12644
12670
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
12645
12671
|
await ctx.database.write(async () => {
|
|
12672
|
+
await assertCanWrite2(ctx);
|
|
12646
12673
|
const writes = [];
|
|
12647
12674
|
for (const id of chunkIds) {
|
|
12648
12675
|
let record2;
|
|
@@ -12675,6 +12702,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
12675
12702
|
const records = await ctx.vaultMemoryCollection.query(Q5.where("user_id", userId), Q5.where("is_deleted", false)).fetch();
|
|
12676
12703
|
if (records.length === 0) return 0;
|
|
12677
12704
|
await ctx.database.write(async () => {
|
|
12705
|
+
await assertCanWrite2(ctx);
|
|
12678
12706
|
const prepared = records.map(
|
|
12679
12707
|
(record2) => record2.prepareUpdate((r) => {
|
|
12680
12708
|
r._setRaw("is_deleted", true);
|
|
@@ -12729,6 +12757,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
12729
12757
|
let stale = false;
|
|
12730
12758
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
12731
12759
|
await ctx.database.write(async () => {
|
|
12760
|
+
await assertCanWrite2(ctx);
|
|
12732
12761
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
12733
12762
|
stale = true;
|
|
12734
12763
|
return;
|
|
@@ -12752,6 +12781,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
12752
12781
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
12753
12782
|
let stale = false;
|
|
12754
12783
|
await ctx.database.write(async () => {
|
|
12784
|
+
await assertCanWrite2(ctx);
|
|
12755
12785
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12756
12786
|
stale = true;
|
|
12757
12787
|
return;
|
|
@@ -12772,6 +12802,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
12772
12802
|
const now = opts.now ?? Date.now();
|
|
12773
12803
|
let stale = false;
|
|
12774
12804
|
await ctx.database.write(async () => {
|
|
12805
|
+
await assertCanWrite2(ctx);
|
|
12775
12806
|
const archivedAt = record2.archivedAt;
|
|
12776
12807
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
12777
12808
|
stale = true;
|
|
@@ -12811,6 +12842,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
|
|
|
12811
12842
|
}
|
|
12812
12843
|
let written = false;
|
|
12813
12844
|
await ctx.database.write(async () => {
|
|
12845
|
+
await assertCanWrite2(ctx);
|
|
12814
12846
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
12815
12847
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12816
12848
|
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
@@ -16323,6 +16355,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
16323
16355
|
).map((c) => c.candidate);
|
|
16324
16356
|
}
|
|
16325
16357
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
16358
|
+
const { memoryStore, signal } = options;
|
|
16359
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
16360
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
16361
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
16362
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
16363
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
16364
|
+
signal?.throwIfAborted();
|
|
16326
16365
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
16327
16366
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
16328
16367
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -16356,6 +16395,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16356
16395
|
}
|
|
16357
16396
|
});
|
|
16358
16397
|
const extractMs = Date.now() - tExtract;
|
|
16398
|
+
signal?.throwIfAborted();
|
|
16359
16399
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
16360
16400
|
const log = getLogger();
|
|
16361
16401
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -16403,16 +16443,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16403
16443
|
const results = [];
|
|
16404
16444
|
const quarantinedInfo = [];
|
|
16405
16445
|
let failedWrites = 0;
|
|
16446
|
+
let auditRows;
|
|
16406
16447
|
const tRetain = Date.now();
|
|
16407
16448
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
16408
16449
|
try {
|
|
16450
|
+
signal?.throwIfAborted();
|
|
16409
16451
|
if (isQuarantined) {
|
|
16410
|
-
|
|
16411
|
-
|
|
16412
|
-
|
|
16413
|
-
|
|
16414
|
-
|
|
16415
|
-
|
|
16452
|
+
let existingId;
|
|
16453
|
+
if (memoryStore) {
|
|
16454
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
16455
|
+
scopes: [options.scope ?? "private"],
|
|
16456
|
+
includeArchived: true,
|
|
16457
|
+
includeQuarantined: true,
|
|
16458
|
+
includeSuperseded: true
|
|
16459
|
+
}));
|
|
16460
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
16461
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
16462
|
+
existingId = (await auditRows).find(
|
|
16463
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
16464
|
+
)?.uniqueId ?? null;
|
|
16465
|
+
} else {
|
|
16466
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
16467
|
+
retainCtx.vaultCtx,
|
|
16468
|
+
candidate.content,
|
|
16469
|
+
candidate.sourceMessageIds,
|
|
16470
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
16471
|
+
).catch(() => null);
|
|
16472
|
+
}
|
|
16416
16473
|
if (existingId) {
|
|
16417
16474
|
quarantinedInfo.push({
|
|
16418
16475
|
candidate,
|
|
@@ -16423,18 +16480,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16423
16480
|
continue;
|
|
16424
16481
|
}
|
|
16425
16482
|
}
|
|
16426
|
-
const
|
|
16483
|
+
const retainOptions = {
|
|
16427
16484
|
source: "auto-extracted",
|
|
16428
16485
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
16429
16486
|
respectTombstones: true,
|
|
16430
16487
|
...options.scope !== void 0 && { scope: options.scope },
|
|
16431
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
16432
16488
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
16433
16489
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
16434
16490
|
factType: candidate.type,
|
|
16435
16491
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
16492
|
+
};
|
|
16493
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
16494
|
+
...retainOptions,
|
|
16495
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
16496
|
+
signal
|
|
16497
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
16498
|
+
...retainOptions,
|
|
16499
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
16436
16500
|
});
|
|
16437
16501
|
if (isQuarantined) {
|
|
16502
|
+
auditRows = void 0;
|
|
16438
16503
|
const info = {
|
|
16439
16504
|
candidate,
|
|
16440
16505
|
memoryId: result.memoryId,
|
|
@@ -16453,9 +16518,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16453
16518
|
}
|
|
16454
16519
|
succeededCandidates.push(candidate);
|
|
16455
16520
|
results.push(result);
|
|
16456
|
-
if (result.action !== "suppressed" &&
|
|
16521
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
16457
16522
|
try {
|
|
16458
|
-
|
|
16523
|
+
signal?.throwIfAborted();
|
|
16524
|
+
if (memoryStore) {
|
|
16525
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
16526
|
+
unlessUserManaged: true,
|
|
16527
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
16528
|
+
signal
|
|
16529
|
+
});
|
|
16530
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
16459
16531
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
16460
16532
|
unlessTopicsUserManaged: true
|
|
16461
16533
|
});
|
|
@@ -16703,7 +16775,7 @@ function createAutoExtractor(options) {
|
|
|
16703
16775
|
};
|
|
16704
16776
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
16705
16777
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
16706
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
16778
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
16707
16779
|
getLogger().warn(
|
|
16708
16780
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
16709
16781
|
);
|
|
@@ -16748,6 +16820,8 @@ function createAutoExtractor(options) {
|
|
|
16748
16820
|
try {
|
|
16749
16821
|
const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
16750
16822
|
extract,
|
|
16823
|
+
memoryStore: options.memoryStore,
|
|
16824
|
+
signal: options.signal,
|
|
16751
16825
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
16752
16826
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
16753
16827
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -18834,6 +18908,7 @@ function createLocalMemoryStore(options) {
|
|
|
18834
18908
|
database,
|
|
18835
18909
|
entityCollection: database.get("entity"),
|
|
18836
18910
|
memoryEntityCollection: database.get("memory_entity"),
|
|
18911
|
+
canWrite: options.canWrite,
|
|
18837
18912
|
...userId !== void 0 && { userId },
|
|
18838
18913
|
...options.allowUnscopedRows !== void 0 && {
|
|
18839
18914
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -18845,10 +18920,21 @@ function createLocalMemoryStore(options) {
|
|
|
18845
18920
|
walletAddress: options.walletAddress,
|
|
18846
18921
|
signMessage: options.signMessage,
|
|
18847
18922
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
18923
|
+
canWrite: options.canWrite,
|
|
18848
18924
|
...userId !== void 0 && { userId },
|
|
18849
18925
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
18850
18926
|
entityCtx
|
|
18851
18927
|
};
|
|
18928
|
+
const assertWrite = async (writeOptions) => {
|
|
18929
|
+
writeOptions?.signal?.throwIfAborted();
|
|
18930
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
18931
|
+
throw new Error("Memory source is no longer eligible");
|
|
18932
|
+
}
|
|
18933
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
18934
|
+
throw new Error("Memory source is no longer eligible");
|
|
18935
|
+
}
|
|
18936
|
+
writeOptions?.signal?.throwIfAborted();
|
|
18937
|
+
};
|
|
18852
18938
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
18853
18939
|
const ownedBy = userId !== void 0 ? [Q8.where("user_id", userId)] : [];
|
|
18854
18940
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [Q8.or(Q8.where("user_id", userId), Q8.where("user_id", null))] : [Q8.where("user_id", userId)];
|
|
@@ -18960,9 +19046,25 @@ function createLocalMemoryStore(options) {
|
|
|
18960
19046
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
18961
19047
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
18962
19048
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
18963
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
19049
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
19050
|
+
await assertWrite(writeOptions);
|
|
18964
19051
|
const owned = await vaultCtx.vaultMemoryCollection.query(Q8.where("id", memoryId), Q8.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
18965
|
-
return owned > 0 ? writer.callWriter(
|
|
19052
|
+
return owned > 0 ? writer.callWriter(
|
|
19053
|
+
() => linkMemoryEntitiesOp(
|
|
19054
|
+
{
|
|
19055
|
+
...entityCtx,
|
|
19056
|
+
canWrite: async () => {
|
|
19057
|
+
await assertWrite(writeOptions);
|
|
19058
|
+
return true;
|
|
19059
|
+
}
|
|
19060
|
+
},
|
|
19061
|
+
memoryId,
|
|
19062
|
+
topics,
|
|
19063
|
+
{
|
|
19064
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
19065
|
+
}
|
|
19066
|
+
)
|
|
19067
|
+
) : [];
|
|
18966
19068
|
}),
|
|
18967
19069
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
18968
19070
|
recall: (query, recallOptions) => recall(
|
|
@@ -18972,7 +19074,17 @@ function createLocalMemoryStore(options) {
|
|
|
18972
19074
|
),
|
|
18973
19075
|
retain: (content, retainOptions) => retain(
|
|
18974
19076
|
content,
|
|
18975
|
-
{
|
|
19077
|
+
{
|
|
19078
|
+
vaultCtx: {
|
|
19079
|
+
...vaultCtx,
|
|
19080
|
+
canWrite: async () => {
|
|
19081
|
+
await assertWrite(retainOptions);
|
|
19082
|
+
return true;
|
|
19083
|
+
}
|
|
19084
|
+
},
|
|
19085
|
+
embeddingOptions: options.embeddingOptions,
|
|
19086
|
+
vaultCache
|
|
19087
|
+
},
|
|
18976
19088
|
retainOptions
|
|
18977
19089
|
),
|
|
18978
19090
|
factSource: {
|
|
@@ -19076,11 +19188,15 @@ function memoryCipher(canonical) {
|
|
|
19076
19188
|
};
|
|
19077
19189
|
}
|
|
19078
19190
|
async function reencryptMemoryField(value, canonical, fallbacks = []) {
|
|
19079
|
-
|
|
19080
|
-
|
|
19191
|
+
return memoryCipher(canonical).encrypt(
|
|
19192
|
+
await decryptMemoryField(value, [canonical, ...fallbacks])
|
|
19193
|
+
);
|
|
19194
|
+
}
|
|
19195
|
+
async function decryptMemoryField(value, rings) {
|
|
19196
|
+
if (!value.startsWith("enc:")) return value;
|
|
19081
19197
|
if (!isEncrypted(value))
|
|
19082
19198
|
throw new MemoryKeyError("Field has an encryption prefix but an invalid payload");
|
|
19083
|
-
return
|
|
19199
|
+
return decryptWith(value, rings);
|
|
19084
19200
|
}
|
|
19085
19201
|
|
|
19086
19202
|
// src/lib/memory/store/remotePersistence.ts
|
|
@@ -19618,7 +19734,14 @@ function stored(row) {
|
|
|
19618
19734
|
function createRemoteMemoryPipeline(options) {
|
|
19619
19735
|
const { persistence, embeddingOptions } = options;
|
|
19620
19736
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19621
|
-
const operation = (mode, queryOptions = embeddingOptions) => {
|
|
19737
|
+
const operation = (mode, queryOptions = embeddingOptions, writeOptions) => {
|
|
19738
|
+
const signal = writeOptions?.signal;
|
|
19739
|
+
const assertWrite = async () => {
|
|
19740
|
+
signal?.throwIfAborted();
|
|
19741
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
19742
|
+
throw new Error("Memory source is no longer eligible");
|
|
19743
|
+
signal?.throwIfAborted();
|
|
19744
|
+
};
|
|
19622
19745
|
const rejectUndecryptable = (failed) => {
|
|
19623
19746
|
if (!failed.length) return;
|
|
19624
19747
|
if (mode === "retain")
|
|
@@ -19636,7 +19759,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19636
19759
|
return items.map((item) => stored(item.memory));
|
|
19637
19760
|
};
|
|
19638
19761
|
const get = async (id) => {
|
|
19639
|
-
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
19762
|
+
const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
19640
19763
|
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
19641
19764
|
snapshots.set(id, snapshot);
|
|
19642
19765
|
return stored(snapshot.memory);
|
|
@@ -19686,7 +19809,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19686
19809
|
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
19687
19810
|
}
|
|
19688
19811
|
const forceIds = [...forced];
|
|
19689
|
-
const windowOptions = (i,
|
|
19812
|
+
const windowOptions = (i, signal2) => ({
|
|
19690
19813
|
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
19691
19814
|
force_ids: i === 0 ? forceIds : [],
|
|
19692
19815
|
...search.scopes && { scopes: search.scopes },
|
|
@@ -19694,13 +19817,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19694
19817
|
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
19695
19818
|
include_archived: search.includeArchived,
|
|
19696
19819
|
embedding_model: model,
|
|
19697
|
-
...
|
|
19820
|
+
...signal2 && { signal: signal2 }
|
|
19698
19821
|
});
|
|
19699
19822
|
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
19700
19823
|
let windows;
|
|
19701
19824
|
if (mode === "retain") {
|
|
19702
19825
|
windows = await Promise.all(
|
|
19703
|
-
vectors.map(
|
|
19826
|
+
vectors.map(
|
|
19827
|
+
(embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
|
|
19828
|
+
)
|
|
19704
19829
|
);
|
|
19705
19830
|
} else {
|
|
19706
19831
|
const deadline = new AbortController();
|
|
@@ -19773,7 +19898,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19773
19898
|
embedding: storedVector(JSON.parse(input.embedding)),
|
|
19774
19899
|
embedding_model: input.embeddingModel
|
|
19775
19900
|
},
|
|
19776
|
-
source_chunk_ids:
|
|
19901
|
+
source_chunk_ids: serializeSourceChunkIds(input.sourceChunkIds ?? []),
|
|
19777
19902
|
proof_count: input.proofCount ?? 1,
|
|
19778
19903
|
source: input.source ?? "manual",
|
|
19779
19904
|
...input.eventTime && {
|
|
@@ -19788,12 +19913,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19788
19913
|
twin_opt_in: false
|
|
19789
19914
|
};
|
|
19790
19915
|
};
|
|
19791
|
-
const write = async (memory, snapshot) =>
|
|
19916
|
+
const write = async (memory, snapshot) => {
|
|
19917
|
+
await assertWrite();
|
|
19918
|
+
return remember([await persistence.put(memory, snapshot, signal)])[0];
|
|
19919
|
+
};
|
|
19792
19920
|
const port = {
|
|
19793
19921
|
prepare,
|
|
19794
19922
|
get,
|
|
19795
19923
|
getFresh: async (id) => {
|
|
19796
|
-
const current = await persistence.get(id);
|
|
19924
|
+
const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
19797
19925
|
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
19798
19926
|
},
|
|
19799
19927
|
tombstones: async (embedding2, embeddingModel, scope, folderId) => {
|
|
@@ -19804,7 +19932,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19804
19932
|
embedding_model: embeddingModel,
|
|
19805
19933
|
strict_model: true,
|
|
19806
19934
|
include_deleted: true,
|
|
19807
|
-
deleted_only: true
|
|
19935
|
+
deleted_only: true,
|
|
19936
|
+
signal
|
|
19808
19937
|
});
|
|
19809
19938
|
rejectUndecryptable(window2.failed);
|
|
19810
19939
|
return remember(window2.items);
|
|
@@ -19832,7 +19961,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19832
19961
|
const observed = sourceIds(memory.source_chunk_ids);
|
|
19833
19962
|
const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
|
|
19834
19963
|
if (patch.sourceChunkIds !== void 0)
|
|
19835
|
-
memory.source_chunk_ids =
|
|
19964
|
+
memory.source_chunk_ids = serializeSourceChunkIds(
|
|
19836
19965
|
patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
|
|
19837
19966
|
);
|
|
19838
19967
|
if (!replay) {
|
|
@@ -19860,14 +19989,18 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19860
19989
|
if (!target || !newer || id === successor) return false;
|
|
19861
19990
|
const old = snapshots.get(id);
|
|
19862
19991
|
const next = snapshots.get(successor);
|
|
19992
|
+
await assertWrite();
|
|
19863
19993
|
remember(
|
|
19864
|
-
await persistence.putMany(
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
|
|
19869
|
-
|
|
19870
|
-
|
|
19994
|
+
await persistence.putMany(
|
|
19995
|
+
[
|
|
19996
|
+
{
|
|
19997
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
19998
|
+
expectedVersion: old
|
|
19999
|
+
},
|
|
20000
|
+
{ memory: next.memory, expectedVersion: next }
|
|
20001
|
+
],
|
|
20002
|
+
signal
|
|
20003
|
+
)
|
|
19871
20004
|
);
|
|
19872
20005
|
return true;
|
|
19873
20006
|
},
|
|
@@ -19876,18 +20009,22 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19876
20009
|
if (!target) return { created: null, retired: false };
|
|
19877
20010
|
const snapshot = snapshots.get(targetId);
|
|
19878
20011
|
const successor = createRow(input);
|
|
20012
|
+
await assertWrite();
|
|
19879
20013
|
const rows = remember(
|
|
19880
|
-
await persistence.putMany(
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
20014
|
+
await persistence.putMany(
|
|
20015
|
+
[
|
|
20016
|
+
{ memory: successor, expectedVersion: 0 },
|
|
20017
|
+
{
|
|
20018
|
+
memory: {
|
|
20019
|
+
...snapshot.memory,
|
|
20020
|
+
superseded_by: successor.memory_id,
|
|
20021
|
+
superseded_at: Date.now()
|
|
20022
|
+
},
|
|
20023
|
+
expectedVersion: snapshot
|
|
20024
|
+
}
|
|
20025
|
+
],
|
|
20026
|
+
signal
|
|
20027
|
+
)
|
|
19891
20028
|
);
|
|
19892
20029
|
return { created: rows[0], retired: true };
|
|
19893
20030
|
}
|
|
@@ -19922,7 +20059,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19922
20059
|
factSource,
|
|
19923
20060
|
recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
|
|
19924
20061
|
retain: async (content, retainOptions) => {
|
|
19925
|
-
const { port } = operation("retain");
|
|
20062
|
+
const { port } = operation("retain", embeddingOptions, retainOptions);
|
|
19926
20063
|
return retainWithPersistence(
|
|
19927
20064
|
content,
|
|
19928
20065
|
{
|
|
@@ -19939,6 +20076,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19939
20076
|
|
|
19940
20077
|
// src/lib/memory/store/remoteMigration.ts
|
|
19941
20078
|
var IMPORT_BATCH = 50;
|
|
20079
|
+
var EMBED_BATCH = 100;
|
|
20080
|
+
var LOCAL_VECTOR_DIMS = 4096;
|
|
19942
20081
|
var VERIFY_BATCH = 1e3;
|
|
19943
20082
|
var QUERY_IDS = 1e3;
|
|
19944
20083
|
var QUERY_PAGE = 200;
|
|
@@ -19964,7 +20103,7 @@ var SHORT_FIELDS = [
|
|
|
19964
20103
|
"visibility",
|
|
19965
20104
|
"geohash"
|
|
19966
20105
|
];
|
|
19967
|
-
var
|
|
20106
|
+
var utf82 = new TextEncoder();
|
|
19968
20107
|
var METADATA_FIELDS = [
|
|
19969
20108
|
"scope",
|
|
19970
20109
|
"kind",
|
|
@@ -20015,17 +20154,34 @@ function revision(raw) {
|
|
|
20015
20154
|
last_observed_at: num(raw.last_observed_at) ?? null
|
|
20016
20155
|
};
|
|
20017
20156
|
}
|
|
20018
|
-
function embedding(raw) {
|
|
20157
|
+
function embedding(raw, model) {
|
|
20019
20158
|
const value = text13(raw.embedding);
|
|
20020
20159
|
if (!value) return void 0;
|
|
20021
20160
|
try {
|
|
20022
|
-
|
|
20161
|
+
const vector = JSON.parse(value);
|
|
20162
|
+
const stored2 = text13(raw.embedding_model);
|
|
20163
|
+
if (stored2 === void 0 ? vector.length !== LOCAL_VECTOR_DIMS : stored2 !== model)
|
|
20164
|
+
return void 0;
|
|
20165
|
+
return storedVector(vector);
|
|
20023
20166
|
} catch {
|
|
20024
20167
|
return void 0;
|
|
20025
20168
|
}
|
|
20026
20169
|
}
|
|
20170
|
+
function stringArray(value) {
|
|
20171
|
+
try {
|
|
20172
|
+
const parsed = JSON.parse(value);
|
|
20173
|
+
return Array.isArray(parsed) && parsed.every((id) => typeof id === "string") ? parsed : void 0;
|
|
20174
|
+
} catch {
|
|
20175
|
+
return void 0;
|
|
20176
|
+
}
|
|
20177
|
+
}
|
|
20178
|
+
function sourceChunkIds(raw) {
|
|
20179
|
+
const value = text13(raw.source_chunk_ids);
|
|
20180
|
+
const ids = value && stringArray(value);
|
|
20181
|
+
return ids ? serializeSourceChunkIds(ids) : value;
|
|
20182
|
+
}
|
|
20027
20183
|
function bytes(value) {
|
|
20028
|
-
return value === void 0 ? 0 :
|
|
20184
|
+
return value === void 0 ? 0 : utf82.encode(value).length;
|
|
20029
20185
|
}
|
|
20030
20186
|
function fitsNearby(row) {
|
|
20031
20187
|
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);
|
|
@@ -20034,16 +20190,16 @@ function invalid(raw) {
|
|
|
20034
20190
|
const id = raw.id;
|
|
20035
20191
|
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;
|
|
20036
20192
|
}
|
|
20037
|
-
function metadata(raw) {
|
|
20038
|
-
const vector = embedding(raw);
|
|
20193
|
+
function metadata(raw, model) {
|
|
20194
|
+
const vector = embedding(raw, model);
|
|
20039
20195
|
return {
|
|
20040
20196
|
scope: raw.scope,
|
|
20041
20197
|
kind: text13(raw.kind),
|
|
20042
20198
|
level: text13(raw.level),
|
|
20043
20199
|
folder_id: text13(raw.folder_id),
|
|
20044
20200
|
is_deleted: bool(raw.is_deleted) ?? false,
|
|
20045
|
-
...vector && { embedding: vector, embedding_model:
|
|
20046
|
-
source_chunk_ids:
|
|
20201
|
+
...vector && { embedding: vector, embedding_model: model },
|
|
20202
|
+
source_chunk_ids: sourceChunkIds(raw),
|
|
20047
20203
|
proof_count: num(raw.proof_count),
|
|
20048
20204
|
source: text13(raw.source),
|
|
20049
20205
|
event_time_start: num(raw.event_time_start),
|
|
@@ -20072,30 +20228,63 @@ function defined(value) {
|
|
|
20072
20228
|
Object.entries(value).filter(([, field10]) => field10 !== void 0)
|
|
20073
20229
|
);
|
|
20074
20230
|
}
|
|
20075
|
-
async function
|
|
20076
|
-
const
|
|
20077
|
-
|
|
20078
|
-
|
|
20079
|
-
|
|
20080
|
-
|
|
20081
|
-
|
|
20082
|
-
|
|
20231
|
+
async function prepareRow(raw, canonical, rings, model, updatedAt) {
|
|
20232
|
+
const deleted = bool(raw.is_deleted) ?? false;
|
|
20233
|
+
const { encrypt } = memoryCipher(canonical);
|
|
20234
|
+
const localKindValue = text13(raw.kind_value);
|
|
20235
|
+
let plaintext;
|
|
20236
|
+
let kindValue;
|
|
20237
|
+
try {
|
|
20238
|
+
plaintext = await decryptMemoryField(typeof raw.content === "string" ? raw.content : "", rings);
|
|
20239
|
+
kindValue = localKindValue && await decryptMemoryField(localKindValue, rings);
|
|
20240
|
+
} catch (error) {
|
|
20241
|
+
if (!deleted || !(error instanceof MemoryKeyError)) throw error;
|
|
20242
|
+
plaintext = void 0;
|
|
20243
|
+
kindValue = void 0;
|
|
20244
|
+
}
|
|
20083
20245
|
const row = {
|
|
20084
|
-
...defined({
|
|
20246
|
+
...defined({
|
|
20247
|
+
...metadata(raw, model),
|
|
20248
|
+
kind_value: kindValue === void 0 ? void 0 : await encrypt(kindValue)
|
|
20249
|
+
}),
|
|
20085
20250
|
memory_id: raw.id,
|
|
20086
|
-
content,
|
|
20251
|
+
content: await encrypt(plaintext ?? ""),
|
|
20087
20252
|
scope: raw.scope,
|
|
20088
20253
|
created_at: raw.created_at,
|
|
20089
20254
|
updated_at: updatedAt,
|
|
20090
|
-
is_deleted:
|
|
20255
|
+
is_deleted: deleted
|
|
20091
20256
|
};
|
|
20092
|
-
return
|
|
20257
|
+
return { row, plaintext };
|
|
20093
20258
|
}
|
|
20094
|
-
function
|
|
20095
|
-
const
|
|
20259
|
+
async function embedMissing(prepared, options, model, signal) {
|
|
20260
|
+
const needed = prepared.filter((p) => !p.row.embedding && p.plaintext);
|
|
20261
|
+
for (const batch of chunks(needed, EMBED_BATCH)) {
|
|
20262
|
+
if (signal?.aborted) throw aborted(signal);
|
|
20263
|
+
try {
|
|
20264
|
+
const vectors = await generateEmbeddings(
|
|
20265
|
+
batch.map((p) => p.plaintext),
|
|
20266
|
+
{ ...options, taskType: "memory_retain_embed" }
|
|
20267
|
+
);
|
|
20268
|
+
if (vectors.length !== batch.length) throw new Error("Incomplete migration embeddings");
|
|
20269
|
+
const stored2 = vectors.map(storedVector);
|
|
20270
|
+
batch.forEach((p, i) => {
|
|
20271
|
+
p.row.embedding = stored2[i];
|
|
20272
|
+
p.row.embedding_model = model;
|
|
20273
|
+
});
|
|
20274
|
+
} catch (error) {
|
|
20275
|
+
getLogger().warn(
|
|
20276
|
+
`[memory/migration] Uploading ${batch.length} row(s) without a vector: embedding failed`,
|
|
20277
|
+
error
|
|
20278
|
+
);
|
|
20279
|
+
}
|
|
20280
|
+
}
|
|
20281
|
+
}
|
|
20282
|
+
function sameMetadata(local, remote, model) {
|
|
20283
|
+
const mine = metadata(local, model);
|
|
20096
20284
|
return METADATA_FIELDS.every((field10) => {
|
|
20097
20285
|
const a = mine[field10] ?? null;
|
|
20098
20286
|
const b = remote[field10] ?? null;
|
|
20287
|
+
if (field10 === "embedding_model" && a === null) return true;
|
|
20099
20288
|
if (field10 === "visibility") return (a ?? "private") === (b ?? "private");
|
|
20100
20289
|
if (field10 === "is_deleted" || field10 === "topics_user_managed" || field10 === "twin_opt_in")
|
|
20101
20290
|
return (a ?? false) === (b ?? false);
|
|
@@ -20191,7 +20380,8 @@ async function backfillTopics(ctx) {
|
|
|
20191
20380
|
}
|
|
20192
20381
|
async function migrateMemoriesToRemote(options) {
|
|
20193
20382
|
const { canonical, signal } = options;
|
|
20194
|
-
const
|
|
20383
|
+
const rings = [canonical, ...options.fallbacks ?? []];
|
|
20384
|
+
const model = options.embeddingOptions?.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
20195
20385
|
const request = createNearbyRequest(options);
|
|
20196
20386
|
const account = await request("/account", {}, signal);
|
|
20197
20387
|
if (typeof account.key_id === "string" && account.key_id !== canonical.keyId)
|
|
@@ -20202,8 +20392,13 @@ async function migrateMemoriesToRemote(options) {
|
|
|
20202
20392
|
);
|
|
20203
20393
|
const active = account.state === "active";
|
|
20204
20394
|
let claimed = account.key_id === canonical.keyId;
|
|
20395
|
+
if (!active) await createDecaySweeper({ vaultCtx: options.vaultCtx }).runSweep();
|
|
20205
20396
|
await backfillTopics(options.vaultCtx);
|
|
20206
20397
|
const skipped = /* @__PURE__ */ new Map();
|
|
20398
|
+
const reembedded = /* @__PURE__ */ new Set();
|
|
20399
|
+
const unembedded = /* @__PURE__ */ new Set();
|
|
20400
|
+
const placeholders = /* @__PURE__ */ new Set();
|
|
20401
|
+
const truncated = /* @__PURE__ */ new Set();
|
|
20207
20402
|
let imported = 0;
|
|
20208
20403
|
for (let pass = 0; ; pass++) {
|
|
20209
20404
|
const rows = await getAllVaultMemoryRowsOp(options.vaultCtx);
|
|
@@ -20219,9 +20414,10 @@ async function migrateMemoriesToRemote(options) {
|
|
|
20219
20414
|
candidates.map((raw) => raw.id),
|
|
20220
20415
|
signal
|
|
20221
20416
|
);
|
|
20417
|
+
const needsVector = (raw, server) => !!options.embeddingOptions && !embedding(raw, model) && server.embedding_model !== model;
|
|
20222
20418
|
for (const raw of candidates) {
|
|
20223
20419
|
const server = remote.get(raw.id);
|
|
20224
|
-
if (server && server.updated_at === raw.updated_at && !sameMetadata(raw, server))
|
|
20420
|
+
if (server && server.updated_at === raw.updated_at && (!sameMetadata(raw, server, model) || needsVector(raw, server)))
|
|
20225
20421
|
pending.set(raw.id, raw.updated_at + 1);
|
|
20226
20422
|
}
|
|
20227
20423
|
}
|
|
@@ -20230,7 +20426,11 @@ async function migrateMemoriesToRemote(options) {
|
|
|
20230
20426
|
state,
|
|
20231
20427
|
total: rows.length,
|
|
20232
20428
|
imported,
|
|
20233
|
-
skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason }))
|
|
20429
|
+
skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason })),
|
|
20430
|
+
reembedded: reembedded.size,
|
|
20431
|
+
unembedded: unembedded.size,
|
|
20432
|
+
placeholderTombstones: placeholders.size,
|
|
20433
|
+
truncatedSourceChunkIds: truncated.size
|
|
20234
20434
|
});
|
|
20235
20435
|
if (skipped.size > 0 && !options.allowSkipped) return result("migrating");
|
|
20236
20436
|
if (!claimed) await importBatch(request, canonical.keyId, [], signal);
|
|
@@ -20248,19 +20448,35 @@ async function migrateMemoriesToRemote(options) {
|
|
|
20248
20448
|
409,
|
|
20249
20449
|
"migration_incomplete"
|
|
20250
20450
|
);
|
|
20251
|
-
const
|
|
20451
|
+
const prepared = [];
|
|
20252
20452
|
for (const raw of candidates) {
|
|
20253
20453
|
const updatedAt = pending.get(raw.id);
|
|
20254
20454
|
if (updatedAt === void 0) continue;
|
|
20255
20455
|
try {
|
|
20256
|
-
|
|
20257
|
-
if (row) upload.push(row);
|
|
20258
|
-
else skipped.set(raw.id, "invalid");
|
|
20456
|
+
prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
|
|
20259
20457
|
} catch (error) {
|
|
20260
20458
|
if (!(error instanceof MemoryKeyError)) throw error;
|
|
20261
20459
|
skipped.set(raw.id, "unreadable");
|
|
20262
20460
|
}
|
|
20263
20461
|
}
|
|
20462
|
+
const usable = new Set(prepared.filter((p) => p.row.embedding).map((p) => p.row.memory_id));
|
|
20463
|
+
if (options.embeddingOptions)
|
|
20464
|
+
await embedMissing(prepared, options.embeddingOptions, model, signal);
|
|
20465
|
+
const local = new Map(candidates.map((raw) => [raw.id, raw]));
|
|
20466
|
+
const upload = [];
|
|
20467
|
+
for (const { row, plaintext } of prepared) {
|
|
20468
|
+
const id = row.memory_id;
|
|
20469
|
+
if (!fitsNearby(row)) {
|
|
20470
|
+
skipped.set(id, "invalid");
|
|
20471
|
+
continue;
|
|
20472
|
+
}
|
|
20473
|
+
upload.push(row);
|
|
20474
|
+
const track = (set, on) => on ? set.add(id) : set.delete(id);
|
|
20475
|
+
track(reembedded, !!row.embedding && !usable.has(id));
|
|
20476
|
+
track(unembedded, !row.embedding);
|
|
20477
|
+
track(placeholders, plaintext === void 0);
|
|
20478
|
+
track(truncated, row.source_chunk_ids !== text13(local.get(id).source_chunk_ids));
|
|
20479
|
+
}
|
|
20264
20480
|
let sent = 0;
|
|
20265
20481
|
options.onProgress?.({ imported: sent, toImport: upload.length });
|
|
20266
20482
|
for (const batch of chunks(upload, IMPORT_BATCH)) {
|
|
@@ -20504,16 +20720,21 @@ function createRemoteMemoryStore(options) {
|
|
|
20504
20720
|
const record2 = await persistence.get(id);
|
|
20505
20721
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
20506
20722
|
};
|
|
20507
|
-
const mutateLocked = async (id, change, edit) => {
|
|
20508
|
-
|
|
20723
|
+
const mutateLocked = async (id, change, edit, writeOptions) => {
|
|
20724
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20725
|
+
const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
|
|
20509
20726
|
if (!record2) return null;
|
|
20727
|
+
if (record2.memory.is_deleted) return null;
|
|
20728
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
20729
|
+
throw new Error("Memory source is no longer eligible");
|
|
20730
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20510
20731
|
const next = edit(structuredClone(record2.memory));
|
|
20511
20732
|
if (!next) return null;
|
|
20512
|
-
const saved = await persistence.put(next, record2);
|
|
20733
|
+
const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
|
|
20513
20734
|
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
20514
20735
|
return saved;
|
|
20515
20736
|
};
|
|
20516
|
-
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
20737
|
+
const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
|
|
20517
20738
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
20518
20739
|
const mutateMany = async (ids, change, edit) => {
|
|
20519
20740
|
const saved = /* @__PURE__ */ new Map();
|
|
@@ -21026,13 +21247,21 @@ function createRemoteMemoryStore(options) {
|
|
|
21026
21247
|
}))
|
|
21027
21248
|
);
|
|
21028
21249
|
},
|
|
21029
|
-
addTopics: async (memoryId, topics) => {
|
|
21250
|
+
addTopics: async (memoryId, topics, writeOptions) => {
|
|
21030
21251
|
const added = await withKnownKinds(topicInputs(topics, "auto"));
|
|
21031
|
-
const saved = await mutate(
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
21035
|
-
|
|
21252
|
+
const saved = await mutate(
|
|
21253
|
+
memoryId,
|
|
21254
|
+
"edit",
|
|
21255
|
+
(memory) => {
|
|
21256
|
+
if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
|
|
21257
|
+
return {
|
|
21258
|
+
...memory,
|
|
21259
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
21260
|
+
topics_updated_at: Date.now()
|
|
21261
|
+
};
|
|
21262
|
+
},
|
|
21263
|
+
writeOptions
|
|
21264
|
+
);
|
|
21036
21265
|
if (!saved) return [];
|
|
21037
21266
|
const now = /* @__PURE__ */ new Date();
|
|
21038
21267
|
return mergeTopics([], added).map(
|
|
@@ -21883,6 +22112,7 @@ function createDurableAutoExtractor(options) {
|
|
|
21883
22112
|
};
|
|
21884
22113
|
const folderId = options.folderId ?? null;
|
|
21885
22114
|
let disposed = false;
|
|
22115
|
+
let activeBatch = null;
|
|
21886
22116
|
let running = false;
|
|
21887
22117
|
let wakeRequested = false;
|
|
21888
22118
|
let timer;
|
|
@@ -21919,14 +22149,18 @@ function createDurableAutoExtractor(options) {
|
|
|
21919
22149
|
}, delay);
|
|
21920
22150
|
}
|
|
21921
22151
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
22152
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
21922
22153
|
let watchdog;
|
|
21923
22154
|
let cancelled = false;
|
|
22155
|
+
const controller = new AbortController();
|
|
22156
|
+
activeBatch = controller;
|
|
21924
22157
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
21925
22158
|
try {
|
|
21926
22159
|
return await Promise.race([
|
|
21927
22160
|
new Promise((resolve, reject) => {
|
|
21928
22161
|
const worker = createAutoExtractor({
|
|
21929
22162
|
...options,
|
|
22163
|
+
signal: controller.signal,
|
|
21930
22164
|
retainCtx: {
|
|
21931
22165
|
...options.retainCtx,
|
|
21932
22166
|
vaultCtx: {
|
|
@@ -21955,6 +22189,8 @@ function createDurableAutoExtractor(options) {
|
|
|
21955
22189
|
]);
|
|
21956
22190
|
} finally {
|
|
21957
22191
|
cancelled = true;
|
|
22192
|
+
controller.abort();
|
|
22193
|
+
if (activeBatch === controller) activeBatch = null;
|
|
21958
22194
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
21959
22195
|
}
|
|
21960
22196
|
}
|
|
@@ -21966,6 +22202,7 @@ function createDurableAutoExtractor(options) {
|
|
|
21966
22202
|
for (const message of loaded)
|
|
21967
22203
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
21968
22204
|
await database.write(async () => {
|
|
22205
|
+
if (disposed) return;
|
|
21969
22206
|
const current = idsOf(job);
|
|
21970
22207
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
21971
22208
|
if (!acknowledged.length) return;
|
|
@@ -22138,6 +22375,7 @@ function createDurableAutoExtractor(options) {
|
|
|
22138
22375
|
jobScope,
|
|
22139
22376
|
jobFolderId
|
|
22140
22377
|
);
|
|
22378
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
22141
22379
|
options.onTurnComplete?.(result);
|
|
22142
22380
|
return result;
|
|
22143
22381
|
};
|
|
@@ -22174,6 +22412,7 @@ function createDurableAutoExtractor(options) {
|
|
|
22174
22412
|
);
|
|
22175
22413
|
scheduleAfterSuccess = true;
|
|
22176
22414
|
} catch (error) {
|
|
22415
|
+
if (disposed) break;
|
|
22177
22416
|
attempts.set(job.id, attempted + 1);
|
|
22178
22417
|
retry = true;
|
|
22179
22418
|
reportError(error, conversationId);
|
|
@@ -22196,6 +22435,14 @@ function createDurableAutoExtractor(options) {
|
|
|
22196
22435
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
22197
22436
|
}
|
|
22198
22437
|
}
|
|
22438
|
+
function dispose() {
|
|
22439
|
+
disposed = true;
|
|
22440
|
+
activeBatch?.abort(options.signal?.reason);
|
|
22441
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
22442
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
22443
|
+
}
|
|
22444
|
+
if (options.signal?.aborted) dispose();
|
|
22445
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
22199
22446
|
schedule(0);
|
|
22200
22447
|
return {
|
|
22201
22448
|
processTurn(messages, conversationId) {
|
|
@@ -22275,10 +22522,7 @@ function createDurableAutoExtractor(options) {
|
|
|
22275
22522
|
return true;
|
|
22276
22523
|
},
|
|
22277
22524
|
isProcessing: () => running,
|
|
22278
|
-
dispose
|
|
22279
|
-
disposed = true;
|
|
22280
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
22281
|
-
}
|
|
22525
|
+
dispose
|
|
22282
22526
|
};
|
|
22283
22527
|
}
|
|
22284
22528
|
|
|
@@ -25527,6 +25771,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
|
|
|
25527
25771
|
var NO_CONVERSATION_KEY = "__no_conversation__";
|
|
25528
25772
|
var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
|
|
25529
25773
|
var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
|
|
25774
|
+
var MEMORY_STORE_NOT_READY = "Memory store is not ready";
|
|
25530
25775
|
var conversationRedactors = /* @__PURE__ */ new Map();
|
|
25531
25776
|
var clientToolFilterCache = /* @__PURE__ */ new Map();
|
|
25532
25777
|
function getConversationRedactor(conversationId, nerDetector) {
|
|
@@ -25671,7 +25916,7 @@ function useChatStorage(options) {
|
|
|
25671
25916
|
[resolvedPiiRedaction]
|
|
25672
25917
|
);
|
|
25673
25918
|
const maskEmbeddingInput = isPiiRedactor(resolvedPiiRedaction) ? maskForEmbedding : void 0;
|
|
25674
|
-
const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
25919
|
+
const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
25675
25920
|
const messagesCollection = useMemo(() => database.get("history"), [database]);
|
|
25676
25921
|
const conversationsCollection = useMemo(
|
|
25677
25922
|
() => database.get("conversations"),
|
|
@@ -25920,6 +26165,7 @@ function useChatStorage(options) {
|
|
|
25920
26165
|
}, [vaultEmbeddingCache]);
|
|
25921
26166
|
const retainVaultMemory = useCallback4(
|
|
25922
26167
|
async (input) => {
|
|
26168
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25923
26169
|
if (memoryStore) {
|
|
25924
26170
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
25925
26171
|
if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -25965,6 +26211,7 @@ function useChatStorage(options) {
|
|
|
25965
26211
|
);
|
|
25966
26212
|
const createMemoryVaultTool2 = useCallback4(
|
|
25967
26213
|
(options2) => {
|
|
26214
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25968
26215
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
25969
26216
|
return createMemoryVaultTool(
|
|
25970
26217
|
memoryStore ?? vaultCtx,
|
|
@@ -25975,6 +26222,7 @@ function useChatStorage(options) {
|
|
|
25975
26222
|
);
|
|
25976
26223
|
const createRecallTool2 = useCallback4(
|
|
25977
26224
|
(toolOptions, callbacks) => {
|
|
26225
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25978
26226
|
if (!getToken && !memoryStore) {
|
|
25979
26227
|
throw new Error("getToken is required for recall tool");
|
|
25980
26228
|
}
|
|
@@ -26020,7 +26268,7 @@ function useChatStorage(options) {
|
|
|
26020
26268
|
);
|
|
26021
26269
|
const recallFn = useCallback4(
|
|
26022
26270
|
async (query, options2) => {
|
|
26023
|
-
if (!getToken && !memoryStore) {
|
|
26271
|
+
if (memoryStore === null || !getToken && !memoryStore) {
|
|
26024
26272
|
return {
|
|
26025
26273
|
memories: [],
|
|
26026
26274
|
usedBudget: options2?.budget ?? "low",
|
|
@@ -26069,6 +26317,7 @@ function useChatStorage(options) {
|
|
|
26069
26317
|
);
|
|
26070
26318
|
const getVaultMemories = useCallback4(
|
|
26071
26319
|
(options2) => {
|
|
26320
|
+
if (memoryStore === null) return Promise.resolve([]);
|
|
26072
26321
|
if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
|
|
26073
26322
|
const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
|
|
26074
26323
|
if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -26079,7 +26328,8 @@ function useChatStorage(options) {
|
|
|
26079
26328
|
[vaultCtx, memoryStore]
|
|
26080
26329
|
);
|
|
26081
26330
|
const deleteVaultMemory = useCallback4(
|
|
26082
|
-
(id) => {
|
|
26331
|
+
async (id) => {
|
|
26332
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
26083
26333
|
return memoryStore ? memoryStore.delete(id) : deleteVaultMemoryOp(vaultCtx, id);
|
|
26084
26334
|
},
|
|
26085
26335
|
[vaultCtx, memoryStore]
|