@anuma/sdk 7.0.3 → 7.0.4-next.20261015012621
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 +388 -130
- package/dist/expo/index.d.mts +25 -12
- package/dist/expo/index.d.ts +25 -12
- package/dist/expo/index.mjs +386 -130
- package/dist/index.cjs +29 -7
- package/dist/index.mjs +29 -7
- package/dist/memory/context.d.mts +1 -0
- package/dist/memory/context.d.ts +1 -0
- package/dist/react/index.cjs +393 -130
- package/dist/react/index.d.mts +25 -12
- package/dist/react/index.d.ts +25 -12
- package/dist/react/index.mjs +391 -130
- package/dist/server/index.cjs +321 -80
- package/dist/server/index.d.mts +27 -4
- package/dist/server/index.d.ts +27 -4
- package/dist/server/index.mjs +319 -80
- package/dist/tools/selection/index.cjs +29 -7
- package/dist/tools/selection/index.mjs +29 -7
- package/package.json +2 -2
package/dist/expo/index.mjs
CHANGED
|
@@ -2158,8 +2158,9 @@ async function updateConversationPinnedOp(ctx, id, pinned) {
|
|
|
2158
2158
|
}
|
|
2159
2159
|
return false;
|
|
2160
2160
|
}
|
|
2161
|
-
async function getMessagesOp(ctx, convId) {
|
|
2162
|
-
const
|
|
2161
|
+
async function getMessagesOp(ctx, convId, opts) {
|
|
2162
|
+
const fetched = await ctx.messagesCollection.query(Q.where("conversation_id", convId), Q.sortBy("message_id", Q.asc)).unsafeFetchRaw();
|
|
2163
|
+
const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
|
|
2163
2164
|
return Promise.all(
|
|
2164
2165
|
results.map(
|
|
2165
2166
|
(raw) => messageRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
@@ -3915,6 +3916,22 @@ var postApiV1Embeddings = (options) => (options.client ?? client).post({
|
|
|
3915
3916
|
});
|
|
3916
3917
|
var getApiV1Models = (options) => (options?.client ?? client).get({ url: "/api/v1/models", ...options });
|
|
3917
3918
|
|
|
3919
|
+
// src/lib/memoryEngine/embeddingCacheState.ts
|
|
3920
|
+
var EMBEDDING_CACHE_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/embedding-cache/v1");
|
|
3921
|
+
var cacheGlobal = globalThis;
|
|
3922
|
+
var fallbackState = {
|
|
3923
|
+
scopedViews: /* @__PURE__ */ new WeakMap(),
|
|
3924
|
+
inFlightByCache: /* @__PURE__ */ new WeakMap(),
|
|
3925
|
+
cachedEmbeddingModels: /* @__PURE__ */ new WeakMap()
|
|
3926
|
+
};
|
|
3927
|
+
function getEmbeddingCacheState() {
|
|
3928
|
+
try {
|
|
3929
|
+
return cacheGlobal[EMBEDDING_CACHE_STATE_KEY] ?? (cacheGlobal[EMBEDDING_CACHE_STATE_KEY] = fallbackState);
|
|
3930
|
+
} catch {
|
|
3931
|
+
return fallbackState;
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3918
3935
|
// src/lib/memoryEngine/generate.ts
|
|
3919
3936
|
var EMBED_MAX_ATTEMPTS = 4;
|
|
3920
3937
|
var DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS = 15e3;
|
|
@@ -4006,15 +4023,18 @@ async function generateEmbedding(text14, options) {
|
|
|
4006
4023
|
if (total === void 0) return embedOne(text14, options, void 0);
|
|
4007
4024
|
return withDeadline((signal) => embedOne(text14, options, signal), total, "embedding");
|
|
4008
4025
|
}
|
|
4009
|
-
var inFlightByCache
|
|
4026
|
+
var { inFlightByCache, cachedEmbeddingModels } = getEmbeddingCacheState();
|
|
4010
4027
|
async function embedOne(text14, options, outer) {
|
|
4011
4028
|
const { cache } = options;
|
|
4012
4029
|
if (!cache) return Array.from(await requestEmbedding(text14, options, outer));
|
|
4030
|
+
const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
4013
4031
|
const cached = cache.get(text14);
|
|
4014
|
-
|
|
4032
|
+
const cachedModel = cached && cachedEmbeddingModels.get(cached);
|
|
4033
|
+
if (cached && (cachedModel === void 0 || cachedModel === model)) return Array.from(cached);
|
|
4015
4034
|
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
4016
4035
|
inFlightByCache.set(cache, inFlight);
|
|
4017
|
-
const
|
|
4036
|
+
const requestKey = JSON.stringify([model, text14]);
|
|
4037
|
+
const pending = inFlight.get(requestKey);
|
|
4018
4038
|
if (pending) {
|
|
4019
4039
|
try {
|
|
4020
4040
|
return Array.from(await pending);
|
|
@@ -4023,13 +4043,14 @@ async function embedOne(text14, options, outer) {
|
|
|
4023
4043
|
}
|
|
4024
4044
|
}
|
|
4025
4045
|
const request = requestEmbedding(text14, options, outer);
|
|
4026
|
-
inFlight.set(
|
|
4046
|
+
inFlight.set(requestKey, request);
|
|
4027
4047
|
try {
|
|
4028
4048
|
const embedding2 = await request;
|
|
4049
|
+
cachedEmbeddingModels.set(embedding2, model);
|
|
4029
4050
|
cache.set(text14, embedding2);
|
|
4030
4051
|
return Array.from(embedding2);
|
|
4031
4052
|
} finally {
|
|
4032
|
-
if (inFlight.get(
|
|
4053
|
+
if (inFlight.get(requestKey) === request) inFlight.delete(requestKey);
|
|
4033
4054
|
}
|
|
4034
4055
|
}
|
|
4035
4056
|
async function requestEmbedding(text14, options, outer) {
|
|
@@ -4112,13 +4133,15 @@ async function embedMany(texts, options, outer) {
|
|
|
4112
4133
|
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
4113
4134
|
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
4114
4135
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
4136
|
+
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
4115
4137
|
const results = new Array(texts.length).fill(null);
|
|
4116
4138
|
const uncachedIndices = [];
|
|
4117
4139
|
const uncachedTexts = [];
|
|
4118
4140
|
for (let i = 0; i < texts.length; i++) {
|
|
4119
4141
|
if (cache) {
|
|
4120
4142
|
const cached = cache.get(texts[i]);
|
|
4121
|
-
|
|
4143
|
+
const cachedModel = cached && cachedEmbeddingModels.get(cached);
|
|
4144
|
+
if (cached && (cachedModel === void 0 || cachedModel === embeddingModel)) {
|
|
4122
4145
|
results[i] = Array.from(cached);
|
|
4123
4146
|
continue;
|
|
4124
4147
|
}
|
|
@@ -4134,7 +4157,6 @@ async function embedMany(texts, options, outer) {
|
|
|
4134
4157
|
...taskTypeHeader(options.taskType)
|
|
4135
4158
|
};
|
|
4136
4159
|
if (outer?.aborted) throw outer.reason;
|
|
4137
|
-
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
4138
4160
|
let newEmbeddings;
|
|
4139
4161
|
if (uncachedTexts.length <= chunkSize) {
|
|
4140
4162
|
newEmbeddings = await generateEmbeddingsBatch(
|
|
@@ -4182,6 +4204,7 @@ async function embedMany(texts, options, outer) {
|
|
|
4182
4204
|
const f32Embedding = Float32Array.from(newEmbeddings[i]);
|
|
4183
4205
|
results[uncachedIndices[i]] = Array.from(f32Embedding);
|
|
4184
4206
|
if (cache) {
|
|
4207
|
+
cachedEmbeddingModels.set(f32Embedding, embeddingModel);
|
|
4185
4208
|
cache.set(uncachedTexts[i], f32Embedding);
|
|
4186
4209
|
}
|
|
4187
4210
|
}
|
|
@@ -4306,6 +4329,37 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
|
|
|
4306
4329
|
}));
|
|
4307
4330
|
return updateMessageChunksOp(ctx, messageId, messageChunks, embeddingModel);
|
|
4308
4331
|
}
|
|
4332
|
+
var MIN_SEALED_EMBEDDING_HEX = 256;
|
|
4333
|
+
function rawHasEmbedding(value) {
|
|
4334
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
4335
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
4336
|
+
if (isEncrypted(value)) {
|
|
4337
|
+
return value.length - value.indexOf(":", 4) - 1 >= MIN_SEALED_EMBEDDING_HEX;
|
|
4338
|
+
}
|
|
4339
|
+
try {
|
|
4340
|
+
const parsed = JSON.parse(value);
|
|
4341
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
4342
|
+
} catch {
|
|
4343
|
+
return false;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
function sealedVersion(value) {
|
|
4347
|
+
if (typeof value !== "string" || !isEncrypted(value)) return null;
|
|
4348
|
+
return value.startsWith("enc:v2:") ? "v2" : "v3";
|
|
4349
|
+
}
|
|
4350
|
+
function mayNeedChunkEmbedding(raw, embeddingModel, filter) {
|
|
4351
|
+
const role = raw.role;
|
|
4352
|
+
if (role === "system") return false;
|
|
4353
|
+
if (filter?.roles && !filter.roles.includes(role ?? "")) return false;
|
|
4354
|
+
if (isNonEmbeddableOrigin(raw.origin, filter?.reembedDiscarded)) {
|
|
4355
|
+
return false;
|
|
4356
|
+
}
|
|
4357
|
+
const model = raw.embedding_model;
|
|
4358
|
+
if (typeof model === "string" && model !== embeddingModel) return true;
|
|
4359
|
+
if (rawHasEmbedding(raw.chunks)) return false;
|
|
4360
|
+
if (rawHasEmbedding(raw.vector) && !filter?.rechunkExisting) return false;
|
|
4361
|
+
return true;
|
|
4362
|
+
}
|
|
4309
4363
|
async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
4310
4364
|
const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
4311
4365
|
const { chunkSize = DEFAULT_CHUNK_SIZE } = options;
|
|
@@ -4318,11 +4372,31 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
4318
4372
|
let considered = 0;
|
|
4319
4373
|
let sealedRowsSeen = 0;
|
|
4320
4374
|
let rowsSeen = 0;
|
|
4375
|
+
const keptSealed = /* @__PURE__ */ new Map();
|
|
4376
|
+
const candidatesStillSealed = /* @__PURE__ */ new Map();
|
|
4377
|
+
const droppedSealed = /* @__PURE__ */ new Map();
|
|
4378
|
+
const rawFilter = (raw) => {
|
|
4379
|
+
rowsSeen++;
|
|
4380
|
+
const keep = mayNeedChunkEmbedding(raw, embeddingModel, filter);
|
|
4381
|
+
const version = sealedVersion(raw.content);
|
|
4382
|
+
if (!version) return keep;
|
|
4383
|
+
if (keep) {
|
|
4384
|
+
keptSealed.set(version, (keptSealed.get(version) ?? 0) + 1);
|
|
4385
|
+
} else {
|
|
4386
|
+
const dropped = droppedSealed.get(version);
|
|
4387
|
+
if (dropped) dropped.count++;
|
|
4388
|
+
else droppedSealed.set(version, { count: 1, probeId: raw.id });
|
|
4389
|
+
}
|
|
4390
|
+
return keep;
|
|
4391
|
+
};
|
|
4321
4392
|
for (const conv of targetConversations) {
|
|
4322
|
-
const messages = await getMessagesOp(ctx, conv.conversationId);
|
|
4393
|
+
const messages = await getMessagesOp(ctx, conv.conversationId, { rawFilter });
|
|
4323
4394
|
for (const message of messages) {
|
|
4324
|
-
|
|
4325
|
-
if (
|
|
4395
|
+
const stillSealed = sealedVersion(message.content);
|
|
4396
|
+
if (stillSealed) {
|
|
4397
|
+
sealedRowsSeen++;
|
|
4398
|
+
candidatesStillSealed.set(stillSealed, (candidatesStillSealed.get(stillSealed) ?? 0) + 1);
|
|
4399
|
+
}
|
|
4326
4400
|
const isStale = message.embeddingModel !== void 0 && message.embeddingModel !== null && message.embeddingModel !== embeddingModel;
|
|
4327
4401
|
if (message.chunks && message.chunks.length > 0 && !isStale) continue;
|
|
4328
4402
|
const hasVector = message.vector && message.vector.length > 0;
|
|
@@ -4335,6 +4409,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
4335
4409
|
stillEncrypted++;
|
|
4336
4410
|
continue;
|
|
4337
4411
|
}
|
|
4412
|
+
if (isToolResultsRow(message)) continue;
|
|
4338
4413
|
if (message.content.length < minLength) continue;
|
|
4339
4414
|
if (shouldChunkMessage(message.content, chunkSize)) {
|
|
4340
4415
|
longMessages.push({
|
|
@@ -4346,6 +4421,12 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
4346
4421
|
}
|
|
4347
4422
|
}
|
|
4348
4423
|
}
|
|
4424
|
+
for (const [version, dropped] of droppedSealed) {
|
|
4425
|
+
const keyOpenedACandidate = (keptSealed.get(version) ?? 0) > (candidatesStillSealed.get(version) ?? 0);
|
|
4426
|
+
if (keyOpenedACandidate) continue;
|
|
4427
|
+
const probe = await getMessageOp(ctx, dropped.probeId);
|
|
4428
|
+
if (!probe || isEncrypted(probe.content)) sealedRowsSeen += dropped.count;
|
|
4429
|
+
}
|
|
4349
4430
|
if (stillEncrypted > 0 || sealedRowsSeen > 0) {
|
|
4350
4431
|
getLogger().error(
|
|
4351
4432
|
"memoryEngine: messages still encrypted (key unavailable?) \u2014 excluded from embedding",
|
|
@@ -9551,7 +9632,7 @@ var MaskScopedEmbeddingCache = class extends Map {
|
|
|
9551
9632
|
return this;
|
|
9552
9633
|
}
|
|
9553
9634
|
};
|
|
9554
|
-
var scopedViews =
|
|
9635
|
+
var { scopedViews } = getEmbeddingCacheState();
|
|
9555
9636
|
function maskScopedEmbeddingCache(cache, masked) {
|
|
9556
9637
|
const views = scopedViews.get(cache) ?? {};
|
|
9557
9638
|
scopedViews.set(cache, views);
|
|
@@ -11050,6 +11131,11 @@ import { Q as Q5 } from "@nozbe/watermelondb";
|
|
|
11050
11131
|
|
|
11051
11132
|
// src/lib/db/entities/operations.ts
|
|
11052
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
|
+
}
|
|
11053
11139
|
function entityToStored(e) {
|
|
11054
11140
|
return {
|
|
11055
11141
|
uniqueId: e.id,
|
|
@@ -11190,6 +11276,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
11190
11276
|
let skipped = false;
|
|
11191
11277
|
let entities = [];
|
|
11192
11278
|
await ctx.database.write(async () => {
|
|
11279
|
+
await assertCanWrite(ctx);
|
|
11193
11280
|
const {
|
|
11194
11281
|
entities: byName,
|
|
11195
11282
|
operations: entityOps,
|
|
@@ -11265,6 +11352,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
11265
11352
|
let skipped = false;
|
|
11266
11353
|
let entities = [];
|
|
11267
11354
|
await ctx.database.write(async () => {
|
|
11355
|
+
await assertCanWrite(ctx);
|
|
11268
11356
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
11269
11357
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
11270
11358
|
skipped = true;
|
|
@@ -11325,6 +11413,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
11325
11413
|
const links = await ctx.memoryEntityCollection.query(Q4.where("memory_id", Q4.oneOf(Array.from(memoryIds)))).fetch();
|
|
11326
11414
|
if (links.length === 0) return;
|
|
11327
11415
|
await ctx.database.write(async () => {
|
|
11416
|
+
await assertCanWrite(ctx);
|
|
11328
11417
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
11329
11418
|
});
|
|
11330
11419
|
}
|
|
@@ -11333,6 +11422,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
11333
11422
|
const links = await ctx.memoryEntityCollection.query(Q4.where("user_id", userId)).fetch();
|
|
11334
11423
|
if (links.length === 0) return;
|
|
11335
11424
|
await ctx.database.write(async () => {
|
|
11425
|
+
await assertCanWrite(ctx);
|
|
11336
11426
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
11337
11427
|
});
|
|
11338
11428
|
}
|
|
@@ -11496,6 +11586,11 @@ function visibilityConditions(requested) {
|
|
|
11496
11586
|
function isKinded(record2) {
|
|
11497
11587
|
return record2.kind !== null && record2.kind !== void 0;
|
|
11498
11588
|
}
|
|
11589
|
+
async function assertCanWrite2(ctx) {
|
|
11590
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
11591
|
+
throw new Error("Memory source is no longer eligible");
|
|
11592
|
+
}
|
|
11593
|
+
}
|
|
11499
11594
|
function assertValidKindLevel(kind, level) {
|
|
11500
11595
|
const hasKind = kind !== null && kind !== void 0;
|
|
11501
11596
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -11676,8 +11771,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
11676
11771
|
ctx.embeddedWalletSigner
|
|
11677
11772
|
) : opts.content;
|
|
11678
11773
|
const created = await ctx.database.write(async () => {
|
|
11679
|
-
|
|
11680
|
-
throw new Error("Memory source is no longer eligible");
|
|
11774
|
+
await assertCanWrite2(ctx);
|
|
11681
11775
|
return ctx.vaultMemoryCollection.create(
|
|
11682
11776
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
11683
11777
|
);
|
|
@@ -11696,8 +11790,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
11696
11790
|
) : opts.content;
|
|
11697
11791
|
let createdRecord = null;
|
|
11698
11792
|
await ctx.database.write(async () => {
|
|
11699
|
-
|
|
11700
|
-
throw new Error("Memory source is no longer eligible");
|
|
11793
|
+
await assertCanWrite2(ctx);
|
|
11701
11794
|
let target;
|
|
11702
11795
|
try {
|
|
11703
11796
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -11789,8 +11882,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
11789
11882
|
})
|
|
11790
11883
|
);
|
|
11791
11884
|
const created = await ctx.database.write(async () => {
|
|
11792
|
-
|
|
11793
|
-
throw new Error("Memory source is no longer eligible");
|
|
11885
|
+
await assertCanWrite2(ctx);
|
|
11794
11886
|
const prepared = optionsArray.map(
|
|
11795
11887
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
11796
11888
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -12095,8 +12187,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
12095
12187
|
const record2 = probe;
|
|
12096
12188
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12097
12189
|
await ctx.database.write(async () => {
|
|
12098
|
-
|
|
12099
|
-
throw new Error("Memory source is no longer eligible");
|
|
12190
|
+
await assertCanWrite2(ctx);
|
|
12100
12191
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
12101
12192
|
stale = true;
|
|
12102
12193
|
return;
|
|
@@ -12207,6 +12298,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
12207
12298
|
let stale = false;
|
|
12208
12299
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12209
12300
|
await ctx.database.write(async (writer) => {
|
|
12301
|
+
await assertCanWrite2(ctx);
|
|
12210
12302
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12211
12303
|
stale = true;
|
|
12212
12304
|
return;
|
|
@@ -12248,6 +12340,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
12248
12340
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12249
12341
|
let cleared = false;
|
|
12250
12342
|
await ctx.database.write(async () => {
|
|
12343
|
+
await assertCanWrite2(ctx);
|
|
12251
12344
|
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
12252
12345
|
cleared = true;
|
|
12253
12346
|
await record2.update((r) => {
|
|
@@ -12271,6 +12364,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
12271
12364
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
12272
12365
|
let stale = false;
|
|
12273
12366
|
await ctx.database.write(async () => {
|
|
12367
|
+
await assertCanWrite2(ctx);
|
|
12274
12368
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12275
12369
|
stale = true;
|
|
12276
12370
|
return;
|
|
@@ -12299,6 +12393,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
12299
12393
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
12300
12394
|
let stale = false;
|
|
12301
12395
|
await ctx.database.write(async () => {
|
|
12396
|
+
await assertCanWrite2(ctx);
|
|
12302
12397
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12303
12398
|
stale = true;
|
|
12304
12399
|
return;
|
|
@@ -12336,8 +12431,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
12336
12431
|
}
|
|
12337
12432
|
let stale = false;
|
|
12338
12433
|
await ctx.database.write(async () => {
|
|
12339
|
-
|
|
12340
|
-
throw new Error("Memory source is no longer eligible");
|
|
12434
|
+
await assertCanWrite2(ctx);
|
|
12341
12435
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
12342
12436
|
stale = true;
|
|
12343
12437
|
return;
|
|
@@ -12499,6 +12593,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
12499
12593
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
12500
12594
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
12501
12595
|
await ctx.database.write(async () => {
|
|
12596
|
+
await assertCanWrite2(ctx);
|
|
12502
12597
|
const records = [];
|
|
12503
12598
|
for (const id of chunkIds) {
|
|
12504
12599
|
try {
|
|
@@ -12532,6 +12627,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
12532
12627
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
12533
12628
|
try {
|
|
12534
12629
|
await ctx.database.write(async (writer) => {
|
|
12630
|
+
await assertCanWrite2(ctx);
|
|
12535
12631
|
let record2;
|
|
12536
12632
|
try {
|
|
12537
12633
|
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -12562,6 +12658,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
12562
12658
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
12563
12659
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
12564
12660
|
await ctx.database.write(async () => {
|
|
12661
|
+
await assertCanWrite2(ctx);
|
|
12565
12662
|
const writes = [];
|
|
12566
12663
|
for (const id of chunkIds) {
|
|
12567
12664
|
let record2;
|
|
@@ -12594,6 +12691,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
12594
12691
|
const records = await ctx.vaultMemoryCollection.query(Q5.where("user_id", userId), Q5.where("is_deleted", false)).fetch();
|
|
12595
12692
|
if (records.length === 0) return 0;
|
|
12596
12693
|
await ctx.database.write(async () => {
|
|
12694
|
+
await assertCanWrite2(ctx);
|
|
12597
12695
|
const prepared = records.map(
|
|
12598
12696
|
(record2) => record2.prepareUpdate((r) => {
|
|
12599
12697
|
r._setRaw("is_deleted", true);
|
|
@@ -12648,6 +12746,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
12648
12746
|
let stale = false;
|
|
12649
12747
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
12650
12748
|
await ctx.database.write(async () => {
|
|
12749
|
+
await assertCanWrite2(ctx);
|
|
12651
12750
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
12652
12751
|
stale = true;
|
|
12653
12752
|
return;
|
|
@@ -12671,6 +12770,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
12671
12770
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
12672
12771
|
let stale = false;
|
|
12673
12772
|
await ctx.database.write(async () => {
|
|
12773
|
+
await assertCanWrite2(ctx);
|
|
12674
12774
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
12675
12775
|
stale = true;
|
|
12676
12776
|
return;
|
|
@@ -12691,6 +12791,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
12691
12791
|
const now = opts.now ?? Date.now();
|
|
12692
12792
|
let stale = false;
|
|
12693
12793
|
await ctx.database.write(async () => {
|
|
12794
|
+
await assertCanWrite2(ctx);
|
|
12694
12795
|
const archivedAt = record2.archivedAt;
|
|
12695
12796
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
12696
12797
|
stale = true;
|
|
@@ -12730,6 +12831,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
|
|
|
12730
12831
|
}
|
|
12731
12832
|
let written = false;
|
|
12732
12833
|
await ctx.database.write(async () => {
|
|
12834
|
+
await assertCanWrite2(ctx);
|
|
12733
12835
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
12734
12836
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
12735
12837
|
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
@@ -16242,6 +16344,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
16242
16344
|
).map((c) => c.candidate);
|
|
16243
16345
|
}
|
|
16244
16346
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
16347
|
+
const { memoryStore, signal } = options;
|
|
16348
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
16349
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
16350
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
16351
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
16352
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
16353
|
+
signal?.throwIfAborted();
|
|
16245
16354
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
16246
16355
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
16247
16356
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -16275,6 +16384,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16275
16384
|
}
|
|
16276
16385
|
});
|
|
16277
16386
|
const extractMs = Date.now() - tExtract;
|
|
16387
|
+
signal?.throwIfAborted();
|
|
16278
16388
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
16279
16389
|
const log = getLogger();
|
|
16280
16390
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -16322,16 +16432,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16322
16432
|
const results = [];
|
|
16323
16433
|
const quarantinedInfo = [];
|
|
16324
16434
|
let failedWrites = 0;
|
|
16435
|
+
let auditRows;
|
|
16325
16436
|
const tRetain = Date.now();
|
|
16326
16437
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
16327
16438
|
try {
|
|
16439
|
+
signal?.throwIfAborted();
|
|
16328
16440
|
if (isQuarantined) {
|
|
16329
|
-
|
|
16330
|
-
|
|
16331
|
-
|
|
16332
|
-
|
|
16333
|
-
|
|
16334
|
-
|
|
16441
|
+
let existingId;
|
|
16442
|
+
if (memoryStore) {
|
|
16443
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
16444
|
+
scopes: [options.scope ?? "private"],
|
|
16445
|
+
includeArchived: true,
|
|
16446
|
+
includeQuarantined: true,
|
|
16447
|
+
includeSuperseded: true
|
|
16448
|
+
}));
|
|
16449
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
16450
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
16451
|
+
existingId = (await auditRows).find(
|
|
16452
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
16453
|
+
)?.uniqueId ?? null;
|
|
16454
|
+
} else {
|
|
16455
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
16456
|
+
retainCtx.vaultCtx,
|
|
16457
|
+
candidate.content,
|
|
16458
|
+
candidate.sourceMessageIds,
|
|
16459
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
16460
|
+
).catch(() => null);
|
|
16461
|
+
}
|
|
16335
16462
|
if (existingId) {
|
|
16336
16463
|
quarantinedInfo.push({
|
|
16337
16464
|
candidate,
|
|
@@ -16342,18 +16469,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16342
16469
|
continue;
|
|
16343
16470
|
}
|
|
16344
16471
|
}
|
|
16345
|
-
const
|
|
16472
|
+
const retainOptions = {
|
|
16346
16473
|
source: "auto-extracted",
|
|
16347
16474
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
16348
16475
|
respectTombstones: true,
|
|
16349
16476
|
...options.scope !== void 0 && { scope: options.scope },
|
|
16350
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
16351
16477
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
16352
16478
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
16353
16479
|
factType: candidate.type,
|
|
16354
16480
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
16481
|
+
};
|
|
16482
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
16483
|
+
...retainOptions,
|
|
16484
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
16485
|
+
signal
|
|
16486
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
16487
|
+
...retainOptions,
|
|
16488
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
16355
16489
|
});
|
|
16356
16490
|
if (isQuarantined) {
|
|
16491
|
+
auditRows = void 0;
|
|
16357
16492
|
const info = {
|
|
16358
16493
|
candidate,
|
|
16359
16494
|
memoryId: result.memoryId,
|
|
@@ -16372,9 +16507,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16372
16507
|
}
|
|
16373
16508
|
succeededCandidates.push(candidate);
|
|
16374
16509
|
results.push(result);
|
|
16375
|
-
if (result.action !== "suppressed" &&
|
|
16510
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
16376
16511
|
try {
|
|
16377
|
-
|
|
16512
|
+
signal?.throwIfAborted();
|
|
16513
|
+
if (memoryStore) {
|
|
16514
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
16515
|
+
unlessUserManaged: true,
|
|
16516
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
16517
|
+
signal
|
|
16518
|
+
});
|
|
16519
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
16378
16520
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
16379
16521
|
unlessTopicsUserManaged: true
|
|
16380
16522
|
});
|
|
@@ -16622,7 +16764,7 @@ function createAutoExtractor(options) {
|
|
|
16622
16764
|
};
|
|
16623
16765
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
16624
16766
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
16625
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
16767
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
16626
16768
|
getLogger().warn(
|
|
16627
16769
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
16628
16770
|
);
|
|
@@ -16667,6 +16809,8 @@ function createAutoExtractor(options) {
|
|
|
16667
16809
|
try {
|
|
16668
16810
|
const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
16669
16811
|
extract,
|
|
16812
|
+
memoryStore: options.memoryStore,
|
|
16813
|
+
signal: options.signal,
|
|
16670
16814
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
16671
16815
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
16672
16816
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -17715,44 +17859,48 @@ async function recall(query, ctx, options = {}) {
|
|
|
17715
17859
|
embeddingOptions,
|
|
17716
17860
|
ctx.vaultCache,
|
|
17717
17861
|
searchOptions
|
|
17718
|
-
)))(
|
|
17719
|
-
|
|
17720
|
-
|
|
17721
|
-
|
|
17722
|
-
|
|
17723
|
-
|
|
17724
|
-
|
|
17725
|
-
|
|
17726
|
-
|
|
17727
|
-
|
|
17728
|
-
|
|
17729
|
-
|
|
17730
|
-
|
|
17731
|
-
|
|
17732
|
-
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
|
|
17736
|
-
|
|
17737
|
-
|
|
17738
|
-
|
|
17739
|
-
|
|
17740
|
-
|
|
17741
|
-
|
|
17862
|
+
)))(
|
|
17863
|
+
query,
|
|
17864
|
+
{
|
|
17865
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
17866
|
+
minSimilarity: vaultMinScore,
|
|
17867
|
+
useFusion: true,
|
|
17868
|
+
rerank: flags.rerank,
|
|
17869
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
17870
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
17871
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
17872
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
17873
|
+
},
|
|
17874
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
17875
|
+
...options.recency && { recency: options.recency },
|
|
17876
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
17877
|
+
...options.supersessionBoost !== void 0 && {
|
|
17878
|
+
supersessionBoost: options.supersessionBoost
|
|
17879
|
+
},
|
|
17880
|
+
...options.supersessionWindow !== void 0 && {
|
|
17881
|
+
supersessionWindow: options.supersessionWindow
|
|
17882
|
+
},
|
|
17883
|
+
...options.proofCountAlpha !== void 0 && {
|
|
17884
|
+
proofCountAlpha: options.proofCountAlpha
|
|
17885
|
+
},
|
|
17886
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
17887
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
17888
|
+
},
|
|
17889
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
17890
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
17891
|
+
...subQueries && { subQueries },
|
|
17892
|
+
...options.scopes && { scopes: options.scopes },
|
|
17893
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
17894
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
17895
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
17896
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
17897
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
17898
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
17899
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
17900
|
+
queryEmbedTotalTimeoutMs
|
|
17742
17901
|
},
|
|
17743
|
-
|
|
17744
|
-
|
|
17745
|
-
...subQueries && { subQueries },
|
|
17746
|
-
...options.scopes && { scopes: options.scopes },
|
|
17747
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
17748
|
-
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
17749
|
-
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
17750
|
-
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
17751
|
-
...entityRanking.length > 0 && { entityRanking },
|
|
17752
|
-
...temporalRanking.length > 0 && { temporalRanking },
|
|
17753
|
-
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
17754
|
-
queryEmbedTotalTimeoutMs
|
|
17755
|
-
});
|
|
17902
|
+
options.embeddingCache
|
|
17903
|
+
);
|
|
17756
17904
|
factResults.push(
|
|
17757
17905
|
...dedupeBy(
|
|
17758
17906
|
results,
|
|
@@ -18749,6 +18897,7 @@ function createLocalMemoryStore(options) {
|
|
|
18749
18897
|
database,
|
|
18750
18898
|
entityCollection: database.get("entity"),
|
|
18751
18899
|
memoryEntityCollection: database.get("memory_entity"),
|
|
18900
|
+
canWrite: options.canWrite,
|
|
18752
18901
|
...userId !== void 0 && { userId },
|
|
18753
18902
|
...options.allowUnscopedRows !== void 0 && {
|
|
18754
18903
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -18760,10 +18909,21 @@ function createLocalMemoryStore(options) {
|
|
|
18760
18909
|
walletAddress: options.walletAddress,
|
|
18761
18910
|
signMessage: options.signMessage,
|
|
18762
18911
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
18912
|
+
canWrite: options.canWrite,
|
|
18763
18913
|
...userId !== void 0 && { userId },
|
|
18764
18914
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
18765
18915
|
entityCtx
|
|
18766
18916
|
};
|
|
18917
|
+
const assertWrite = async (writeOptions) => {
|
|
18918
|
+
writeOptions?.signal?.throwIfAborted();
|
|
18919
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
18920
|
+
throw new Error("Memory source is no longer eligible");
|
|
18921
|
+
}
|
|
18922
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
18923
|
+
throw new Error("Memory source is no longer eligible");
|
|
18924
|
+
}
|
|
18925
|
+
writeOptions?.signal?.throwIfAborted();
|
|
18926
|
+
};
|
|
18767
18927
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
18768
18928
|
const ownedBy = userId !== void 0 ? [Q8.where("user_id", userId)] : [];
|
|
18769
18929
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [Q8.or(Q8.where("user_id", userId), Q8.where("user_id", null))] : [Q8.where("user_id", userId)];
|
|
@@ -18875,9 +19035,25 @@ function createLocalMemoryStore(options) {
|
|
|
18875
19035
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
18876
19036
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
18877
19037
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
18878
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
19038
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
19039
|
+
await assertWrite(writeOptions);
|
|
18879
19040
|
const owned = await vaultCtx.vaultMemoryCollection.query(Q8.where("id", memoryId), Q8.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
18880
|
-
return owned > 0 ? writer.callWriter(
|
|
19041
|
+
return owned > 0 ? writer.callWriter(
|
|
19042
|
+
() => linkMemoryEntitiesOp(
|
|
19043
|
+
{
|
|
19044
|
+
...entityCtx,
|
|
19045
|
+
canWrite: async () => {
|
|
19046
|
+
await assertWrite(writeOptions);
|
|
19047
|
+
return true;
|
|
19048
|
+
}
|
|
19049
|
+
},
|
|
19050
|
+
memoryId,
|
|
19051
|
+
topics,
|
|
19052
|
+
{
|
|
19053
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
19054
|
+
}
|
|
19055
|
+
)
|
|
19056
|
+
) : [];
|
|
18881
19057
|
}),
|
|
18882
19058
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
18883
19059
|
recall: (query, recallOptions) => recall(
|
|
@@ -18887,14 +19063,33 @@ function createLocalMemoryStore(options) {
|
|
|
18887
19063
|
),
|
|
18888
19064
|
retain: (content, retainOptions) => retain(
|
|
18889
19065
|
content,
|
|
18890
|
-
{
|
|
19066
|
+
{
|
|
19067
|
+
vaultCtx: {
|
|
19068
|
+
...vaultCtx,
|
|
19069
|
+
canWrite: async () => {
|
|
19070
|
+
await assertWrite(retainOptions);
|
|
19071
|
+
return true;
|
|
19072
|
+
}
|
|
19073
|
+
},
|
|
19074
|
+
embeddingOptions: options.embeddingOptions,
|
|
19075
|
+
vaultCache
|
|
19076
|
+
},
|
|
18891
19077
|
retainOptions
|
|
18892
19078
|
),
|
|
18893
19079
|
factSource: {
|
|
18894
|
-
search: (query, searchOptions) => searchVaultMemoriesWithSize(
|
|
19080
|
+
search: (query, searchOptions, embeddingCache) => searchVaultMemoriesWithSize(
|
|
18895
19081
|
query,
|
|
18896
19082
|
vaultCtx,
|
|
18897
|
-
{
|
|
19083
|
+
{
|
|
19084
|
+
...options.embeddingOptions,
|
|
19085
|
+
taskType: "memory_recall_embed",
|
|
19086
|
+
...embeddingCache && !options.embeddingOptions.cache && {
|
|
19087
|
+
cache: maskScopedEmbeddingCache(
|
|
19088
|
+
embeddingCache,
|
|
19089
|
+
Boolean(options.embeddingOptions.maskInput)
|
|
19090
|
+
)
|
|
19091
|
+
}
|
|
19092
|
+
},
|
|
18898
19093
|
vaultCache,
|
|
18899
19094
|
searchOptions
|
|
18900
19095
|
),
|
|
@@ -19524,7 +19719,14 @@ function stored(row) {
|
|
|
19524
19719
|
function createRemoteMemoryPipeline(options) {
|
|
19525
19720
|
const { persistence, embeddingOptions } = options;
|
|
19526
19721
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19527
|
-
const operation = (mode) => {
|
|
19722
|
+
const operation = (mode, queryOptions = embeddingOptions, writeOptions) => {
|
|
19723
|
+
const signal = writeOptions?.signal;
|
|
19724
|
+
const assertWrite = async () => {
|
|
19725
|
+
signal?.throwIfAborted();
|
|
19726
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
19727
|
+
throw new Error("Memory source is no longer eligible");
|
|
19728
|
+
signal?.throwIfAborted();
|
|
19729
|
+
};
|
|
19528
19730
|
const rejectUndecryptable = (failed) => {
|
|
19529
19731
|
if (!failed.length) return;
|
|
19530
19732
|
if (mode === "retain")
|
|
@@ -19542,7 +19744,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19542
19744
|
return items.map((item) => stored(item.memory));
|
|
19543
19745
|
};
|
|
19544
19746
|
const get = async (id) => {
|
|
19545
|
-
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
19747
|
+
const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
19546
19748
|
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
19547
19749
|
snapshots.set(id, snapshot);
|
|
19548
19750
|
return stored(snapshot.memory);
|
|
@@ -19555,7 +19757,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19555
19757
|
const start = Date.now();
|
|
19556
19758
|
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
19557
19759
|
const embed = (texts) => generateEmbeddings(texts, {
|
|
19558
|
-
...
|
|
19760
|
+
...queryOptions,
|
|
19559
19761
|
taskType: mode === "retain" ? "memory_retain_embed" : "memory_recall_embed",
|
|
19560
19762
|
totalTimeoutMs: budgetMs
|
|
19561
19763
|
});
|
|
@@ -19575,7 +19777,11 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19575
19777
|
}
|
|
19576
19778
|
};
|
|
19577
19779
|
const [primary, facetEmbeddings] = await Promise.all([
|
|
19578
|
-
search.queryEmbedding ??
|
|
19780
|
+
search.queryEmbedding ?? (mode === "recall" && queryOptions.cache ? generateEmbedding(query, {
|
|
19781
|
+
...queryOptions,
|
|
19782
|
+
taskType: "memory_recall_embed",
|
|
19783
|
+
totalTimeoutMs: budgetMs
|
|
19784
|
+
}) : embed([query]).then((vectors2) => vectors2[0])),
|
|
19579
19785
|
embedFacets()
|
|
19580
19786
|
]);
|
|
19581
19787
|
const queryEmbedding = storedVector(primary);
|
|
@@ -19588,7 +19794,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19588
19794
|
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
19589
19795
|
}
|
|
19590
19796
|
const forceIds = [...forced];
|
|
19591
|
-
const windowOptions = (i,
|
|
19797
|
+
const windowOptions = (i, signal2) => ({
|
|
19592
19798
|
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
19593
19799
|
force_ids: i === 0 ? forceIds : [],
|
|
19594
19800
|
...search.scopes && { scopes: search.scopes },
|
|
@@ -19596,13 +19802,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19596
19802
|
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
19597
19803
|
include_archived: search.includeArchived,
|
|
19598
19804
|
embedding_model: model,
|
|
19599
|
-
...
|
|
19805
|
+
...signal2 && { signal: signal2 }
|
|
19600
19806
|
});
|
|
19601
19807
|
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
19602
19808
|
let windows;
|
|
19603
19809
|
if (mode === "retain") {
|
|
19604
19810
|
windows = await Promise.all(
|
|
19605
|
-
vectors.map(
|
|
19811
|
+
vectors.map(
|
|
19812
|
+
(embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
|
|
19813
|
+
)
|
|
19606
19814
|
);
|
|
19607
19815
|
} else {
|
|
19608
19816
|
const deadline = new AbortController();
|
|
@@ -19690,12 +19898,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19690
19898
|
twin_opt_in: false
|
|
19691
19899
|
};
|
|
19692
19900
|
};
|
|
19693
|
-
const write = async (memory, snapshot) =>
|
|
19901
|
+
const write = async (memory, snapshot) => {
|
|
19902
|
+
await assertWrite();
|
|
19903
|
+
return remember([await persistence.put(memory, snapshot, signal)])[0];
|
|
19904
|
+
};
|
|
19694
19905
|
const port = {
|
|
19695
19906
|
prepare,
|
|
19696
19907
|
get,
|
|
19697
19908
|
getFresh: async (id) => {
|
|
19698
|
-
const current = await persistence.get(id);
|
|
19909
|
+
const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
19699
19910
|
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
19700
19911
|
},
|
|
19701
19912
|
tombstones: async (embedding2, embeddingModel, scope, folderId) => {
|
|
@@ -19706,7 +19917,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19706
19917
|
embedding_model: embeddingModel,
|
|
19707
19918
|
strict_model: true,
|
|
19708
19919
|
include_deleted: true,
|
|
19709
|
-
deleted_only: true
|
|
19920
|
+
deleted_only: true,
|
|
19921
|
+
signal
|
|
19710
19922
|
});
|
|
19711
19923
|
rejectUndecryptable(window2.failed);
|
|
19712
19924
|
return remember(window2.items);
|
|
@@ -19762,14 +19974,18 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19762
19974
|
if (!target || !newer || id === successor) return false;
|
|
19763
19975
|
const old = snapshots.get(id);
|
|
19764
19976
|
const next = snapshots.get(successor);
|
|
19977
|
+
await assertWrite();
|
|
19765
19978
|
remember(
|
|
19766
|
-
await persistence.putMany(
|
|
19767
|
-
|
|
19768
|
-
|
|
19769
|
-
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
19979
|
+
await persistence.putMany(
|
|
19980
|
+
[
|
|
19981
|
+
{
|
|
19982
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
19983
|
+
expectedVersion: old
|
|
19984
|
+
},
|
|
19985
|
+
{ memory: next.memory, expectedVersion: next }
|
|
19986
|
+
],
|
|
19987
|
+
signal
|
|
19988
|
+
)
|
|
19773
19989
|
);
|
|
19774
19990
|
return true;
|
|
19775
19991
|
},
|
|
@@ -19778,18 +19994,22 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19778
19994
|
if (!target) return { created: null, retired: false };
|
|
19779
19995
|
const snapshot = snapshots.get(targetId);
|
|
19780
19996
|
const successor = createRow(input);
|
|
19997
|
+
await assertWrite();
|
|
19781
19998
|
const rows = remember(
|
|
19782
|
-
await persistence.putMany(
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
|
|
19788
|
-
|
|
19789
|
-
|
|
19790
|
-
|
|
19791
|
-
|
|
19792
|
-
|
|
19999
|
+
await persistence.putMany(
|
|
20000
|
+
[
|
|
20001
|
+
{ memory: successor, expectedVersion: 0 },
|
|
20002
|
+
{
|
|
20003
|
+
memory: {
|
|
20004
|
+
...snapshot.memory,
|
|
20005
|
+
superseded_by: successor.memory_id,
|
|
20006
|
+
superseded_at: Date.now()
|
|
20007
|
+
},
|
|
20008
|
+
expectedVersion: snapshot
|
|
20009
|
+
}
|
|
20010
|
+
],
|
|
20011
|
+
signal
|
|
20012
|
+
)
|
|
19793
20013
|
);
|
|
19794
20014
|
return { created: rows[0], retired: true };
|
|
19795
20015
|
}
|
|
@@ -19799,15 +20019,17 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19799
20019
|
const factSource = {
|
|
19800
20020
|
graphRanking: options.graphRanking,
|
|
19801
20021
|
temporalRanking: options.temporalRanking,
|
|
19802
|
-
search: async (text14, searchOptions) => {
|
|
19803
|
-
const
|
|
20022
|
+
search: async (text14, searchOptions, embeddingCache) => {
|
|
20023
|
+
const queryOptions = {
|
|
20024
|
+
...embeddingOptions,
|
|
20025
|
+
taskType: "memory_recall_embed",
|
|
20026
|
+
...embeddingCache && !embeddingOptions.cache && {
|
|
20027
|
+
cache: maskScopedEmbeddingCache(embeddingCache, Boolean(embeddingOptions.maskInput))
|
|
20028
|
+
}
|
|
20029
|
+
};
|
|
20030
|
+
const { prepare } = operation("recall", queryOptions);
|
|
19804
20031
|
const prepared = await prepare(text14, searchOptions);
|
|
19805
|
-
const ranked = await rankPreparedVaultCandidates(
|
|
19806
|
-
text14,
|
|
19807
|
-
prepared,
|
|
19808
|
-
{ ...embeddingOptions, taskType: "memory_recall_embed" },
|
|
19809
|
-
searchOptions
|
|
19810
|
-
);
|
|
20032
|
+
const ranked = await rankPreparedVaultCandidates(text14, prepared, queryOptions, searchOptions);
|
|
19811
20033
|
return {
|
|
19812
20034
|
...ranked,
|
|
19813
20035
|
rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
|
|
@@ -19822,7 +20044,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19822
20044
|
factSource,
|
|
19823
20045
|
recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
|
|
19824
20046
|
retain: async (content, retainOptions) => {
|
|
19825
|
-
const { port } = operation("retain");
|
|
20047
|
+
const { port } = operation("retain", embeddingOptions, retainOptions);
|
|
19826
20048
|
return retainWithPersistence(
|
|
19827
20049
|
content,
|
|
19828
20050
|
{
|
|
@@ -20404,16 +20626,21 @@ function createRemoteMemoryStore(options) {
|
|
|
20404
20626
|
const record2 = await persistence.get(id);
|
|
20405
20627
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
20406
20628
|
};
|
|
20407
|
-
const mutateLocked = async (id, change, edit) => {
|
|
20408
|
-
|
|
20629
|
+
const mutateLocked = async (id, change, edit, writeOptions) => {
|
|
20630
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20631
|
+
const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
|
|
20409
20632
|
if (!record2) return null;
|
|
20633
|
+
if (record2.memory.is_deleted) return null;
|
|
20634
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
20635
|
+
throw new Error("Memory source is no longer eligible");
|
|
20636
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20410
20637
|
const next = edit(structuredClone(record2.memory));
|
|
20411
20638
|
if (!next) return null;
|
|
20412
|
-
const saved = await persistence.put(next, record2);
|
|
20639
|
+
const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
|
|
20413
20640
|
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
20414
20641
|
return saved;
|
|
20415
20642
|
};
|
|
20416
|
-
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
20643
|
+
const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
|
|
20417
20644
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
20418
20645
|
const mutateMany = async (ids, change, edit) => {
|
|
20419
20646
|
const saved = /* @__PURE__ */ new Map();
|
|
@@ -20926,13 +21153,21 @@ function createRemoteMemoryStore(options) {
|
|
|
20926
21153
|
}))
|
|
20927
21154
|
);
|
|
20928
21155
|
},
|
|
20929
|
-
addTopics: async (memoryId, topics) => {
|
|
21156
|
+
addTopics: async (memoryId, topics, writeOptions) => {
|
|
20930
21157
|
const added = await withKnownKinds(topicInputs(topics, "auto"));
|
|
20931
|
-
const saved = await mutate(
|
|
20932
|
-
|
|
20933
|
-
|
|
20934
|
-
|
|
20935
|
-
|
|
21158
|
+
const saved = await mutate(
|
|
21159
|
+
memoryId,
|
|
21160
|
+
"edit",
|
|
21161
|
+
(memory) => {
|
|
21162
|
+
if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
|
|
21163
|
+
return {
|
|
21164
|
+
...memory,
|
|
21165
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
21166
|
+
topics_updated_at: Date.now()
|
|
21167
|
+
};
|
|
21168
|
+
},
|
|
21169
|
+
writeOptions
|
|
21170
|
+
);
|
|
20936
21171
|
if (!saved) return [];
|
|
20937
21172
|
const now = /* @__PURE__ */ new Date();
|
|
20938
21173
|
return mergeTopics([], added).map(
|
|
@@ -21783,6 +22018,7 @@ function createDurableAutoExtractor(options) {
|
|
|
21783
22018
|
};
|
|
21784
22019
|
const folderId = options.folderId ?? null;
|
|
21785
22020
|
let disposed = false;
|
|
22021
|
+
let activeBatch = null;
|
|
21786
22022
|
let running = false;
|
|
21787
22023
|
let wakeRequested = false;
|
|
21788
22024
|
let timer;
|
|
@@ -21819,14 +22055,18 @@ function createDurableAutoExtractor(options) {
|
|
|
21819
22055
|
}, delay);
|
|
21820
22056
|
}
|
|
21821
22057
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
22058
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
21822
22059
|
let watchdog;
|
|
21823
22060
|
let cancelled = false;
|
|
22061
|
+
const controller = new AbortController();
|
|
22062
|
+
activeBatch = controller;
|
|
21824
22063
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
21825
22064
|
try {
|
|
21826
22065
|
return await Promise.race([
|
|
21827
22066
|
new Promise((resolve, reject) => {
|
|
21828
22067
|
const worker = createAutoExtractor({
|
|
21829
22068
|
...options,
|
|
22069
|
+
signal: controller.signal,
|
|
21830
22070
|
retainCtx: {
|
|
21831
22071
|
...options.retainCtx,
|
|
21832
22072
|
vaultCtx: {
|
|
@@ -21855,6 +22095,8 @@ function createDurableAutoExtractor(options) {
|
|
|
21855
22095
|
]);
|
|
21856
22096
|
} finally {
|
|
21857
22097
|
cancelled = true;
|
|
22098
|
+
controller.abort();
|
|
22099
|
+
if (activeBatch === controller) activeBatch = null;
|
|
21858
22100
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
21859
22101
|
}
|
|
21860
22102
|
}
|
|
@@ -21866,6 +22108,7 @@ function createDurableAutoExtractor(options) {
|
|
|
21866
22108
|
for (const message of loaded)
|
|
21867
22109
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
21868
22110
|
await database.write(async () => {
|
|
22111
|
+
if (disposed) return;
|
|
21869
22112
|
const current = idsOf(job);
|
|
21870
22113
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
21871
22114
|
if (!acknowledged.length) return;
|
|
@@ -22038,6 +22281,7 @@ function createDurableAutoExtractor(options) {
|
|
|
22038
22281
|
jobScope,
|
|
22039
22282
|
jobFolderId
|
|
22040
22283
|
);
|
|
22284
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
22041
22285
|
options.onTurnComplete?.(result);
|
|
22042
22286
|
return result;
|
|
22043
22287
|
};
|
|
@@ -22074,6 +22318,7 @@ function createDurableAutoExtractor(options) {
|
|
|
22074
22318
|
);
|
|
22075
22319
|
scheduleAfterSuccess = true;
|
|
22076
22320
|
} catch (error) {
|
|
22321
|
+
if (disposed) break;
|
|
22077
22322
|
attempts.set(job.id, attempted + 1);
|
|
22078
22323
|
retry = true;
|
|
22079
22324
|
reportError(error, conversationId);
|
|
@@ -22096,6 +22341,14 @@ function createDurableAutoExtractor(options) {
|
|
|
22096
22341
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
22097
22342
|
}
|
|
22098
22343
|
}
|
|
22344
|
+
function dispose() {
|
|
22345
|
+
disposed = true;
|
|
22346
|
+
activeBatch?.abort(options.signal?.reason);
|
|
22347
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
22348
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
22349
|
+
}
|
|
22350
|
+
if (options.signal?.aborted) dispose();
|
|
22351
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
22099
22352
|
schedule(0);
|
|
22100
22353
|
return {
|
|
22101
22354
|
processTurn(messages, conversationId) {
|
|
@@ -22175,10 +22428,7 @@ function createDurableAutoExtractor(options) {
|
|
|
22175
22428
|
return true;
|
|
22176
22429
|
},
|
|
22177
22430
|
isProcessing: () => running,
|
|
22178
|
-
dispose
|
|
22179
|
-
disposed = true;
|
|
22180
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
22181
|
-
}
|
|
22431
|
+
dispose
|
|
22182
22432
|
};
|
|
22183
22433
|
}
|
|
22184
22434
|
|
|
@@ -25427,6 +25677,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
|
|
|
25427
25677
|
var NO_CONVERSATION_KEY = "__no_conversation__";
|
|
25428
25678
|
var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
|
|
25429
25679
|
var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
|
|
25680
|
+
var MEMORY_STORE_NOT_READY = "Memory store is not ready";
|
|
25430
25681
|
var conversationRedactors = /* @__PURE__ */ new Map();
|
|
25431
25682
|
var clientToolFilterCache = /* @__PURE__ */ new Map();
|
|
25432
25683
|
function getConversationRedactor(conversationId, nerDetector) {
|
|
@@ -25571,7 +25822,7 @@ function useChatStorage(options) {
|
|
|
25571
25822
|
[resolvedPiiRedaction]
|
|
25572
25823
|
);
|
|
25573
25824
|
const maskEmbeddingInput = isPiiRedactor(resolvedPiiRedaction) ? maskForEmbedding : void 0;
|
|
25574
|
-
const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
25825
|
+
const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
25575
25826
|
const messagesCollection = useMemo(() => database.get("history"), [database]);
|
|
25576
25827
|
const conversationsCollection = useMemo(
|
|
25577
25828
|
() => database.get("conversations"),
|
|
@@ -25820,6 +26071,7 @@ function useChatStorage(options) {
|
|
|
25820
26071
|
}, [vaultEmbeddingCache]);
|
|
25821
26072
|
const retainVaultMemory = useCallback4(
|
|
25822
26073
|
async (input) => {
|
|
26074
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25823
26075
|
if (memoryStore) {
|
|
25824
26076
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
25825
26077
|
if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -25865,6 +26117,7 @@ function useChatStorage(options) {
|
|
|
25865
26117
|
);
|
|
25866
26118
|
const createMemoryVaultTool2 = useCallback4(
|
|
25867
26119
|
(options2) => {
|
|
26120
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25868
26121
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
25869
26122
|
return createMemoryVaultTool(
|
|
25870
26123
|
memoryStore ?? vaultCtx,
|
|
@@ -25875,6 +26128,7 @@ function useChatStorage(options) {
|
|
|
25875
26128
|
);
|
|
25876
26129
|
const createRecallTool2 = useCallback4(
|
|
25877
26130
|
(toolOptions, callbacks) => {
|
|
26131
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25878
26132
|
if (!getToken && !memoryStore) {
|
|
25879
26133
|
throw new Error("getToken is required for recall tool");
|
|
25880
26134
|
}
|
|
@@ -25920,7 +26174,7 @@ function useChatStorage(options) {
|
|
|
25920
26174
|
);
|
|
25921
26175
|
const recallFn = useCallback4(
|
|
25922
26176
|
async (query, options2) => {
|
|
25923
|
-
if (!getToken && !memoryStore) {
|
|
26177
|
+
if (memoryStore === null || !getToken && !memoryStore) {
|
|
25924
26178
|
return {
|
|
25925
26179
|
memories: [],
|
|
25926
26180
|
usedBudget: options2?.budget ?? "low",
|
|
@@ -25969,6 +26223,7 @@ function useChatStorage(options) {
|
|
|
25969
26223
|
);
|
|
25970
26224
|
const getVaultMemories = useCallback4(
|
|
25971
26225
|
(options2) => {
|
|
26226
|
+
if (memoryStore === null) return Promise.resolve([]);
|
|
25972
26227
|
if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
|
|
25973
26228
|
const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
|
|
25974
26229
|
if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -25979,7 +26234,8 @@ function useChatStorage(options) {
|
|
|
25979
26234
|
[vaultCtx, memoryStore]
|
|
25980
26235
|
);
|
|
25981
26236
|
const deleteVaultMemory = useCallback4(
|
|
25982
|
-
(id) => {
|
|
26237
|
+
async (id) => {
|
|
26238
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
25983
26239
|
return memoryStore ? memoryStore.delete(id) : deleteVaultMemoryOp(vaultCtx, id);
|
|
25984
26240
|
},
|
|
25985
26241
|
[vaultCtx, memoryStore]
|