@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.cjs
CHANGED
|
@@ -3731,8 +3731,9 @@ async function updateConversationPinnedOp(ctx, id, pinned) {
|
|
|
3731
3731
|
}
|
|
3732
3732
|
return false;
|
|
3733
3733
|
}
|
|
3734
|
-
async function getMessagesOp(ctx, convId) {
|
|
3735
|
-
const
|
|
3734
|
+
async function getMessagesOp(ctx, convId, opts) {
|
|
3735
|
+
const fetched = await ctx.messagesCollection.query(import_watermelondb2.Q.where("conversation_id", convId), import_watermelondb2.Q.sortBy("message_id", import_watermelondb2.Q.asc)).unsafeFetchRaw();
|
|
3736
|
+
const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
|
|
3736
3737
|
return Promise.all(
|
|
3737
3738
|
results.map(
|
|
3738
3739
|
(raw) => messageRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
@@ -5495,6 +5496,24 @@ var getApiV1Models = (options) => (options?.client ?? client).get({ url: "/api/v
|
|
|
5495
5496
|
// src/lib/memoryEngine/generate.ts
|
|
5496
5497
|
init_clientConfig();
|
|
5497
5498
|
init_taskType();
|
|
5499
|
+
|
|
5500
|
+
// src/lib/memoryEngine/embeddingCacheState.ts
|
|
5501
|
+
var EMBEDDING_CACHE_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/embedding-cache/v1");
|
|
5502
|
+
var cacheGlobal = globalThis;
|
|
5503
|
+
var fallbackState = {
|
|
5504
|
+
scopedViews: /* @__PURE__ */ new WeakMap(),
|
|
5505
|
+
inFlightByCache: /* @__PURE__ */ new WeakMap(),
|
|
5506
|
+
cachedEmbeddingModels: /* @__PURE__ */ new WeakMap()
|
|
5507
|
+
};
|
|
5508
|
+
function getEmbeddingCacheState() {
|
|
5509
|
+
try {
|
|
5510
|
+
return cacheGlobal[EMBEDDING_CACHE_STATE_KEY] ?? (cacheGlobal[EMBEDDING_CACHE_STATE_KEY] = fallbackState);
|
|
5511
|
+
} catch {
|
|
5512
|
+
return fallbackState;
|
|
5513
|
+
}
|
|
5514
|
+
}
|
|
5515
|
+
|
|
5516
|
+
// src/lib/memoryEngine/generate.ts
|
|
5498
5517
|
var EMBED_MAX_ATTEMPTS = 4;
|
|
5499
5518
|
var DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS = 15e3;
|
|
5500
5519
|
var DEFAULT_EMBEDDING_TOKEN_TIMEOUT_MS = 1e4;
|
|
@@ -5585,15 +5604,18 @@ async function generateEmbedding(text14, options) {
|
|
|
5585
5604
|
if (total === void 0) return embedOne(text14, options, void 0);
|
|
5586
5605
|
return withDeadline((signal) => embedOne(text14, options, signal), total, "embedding");
|
|
5587
5606
|
}
|
|
5588
|
-
var inFlightByCache
|
|
5607
|
+
var { inFlightByCache, cachedEmbeddingModels } = getEmbeddingCacheState();
|
|
5589
5608
|
async function embedOne(text14, options, outer) {
|
|
5590
5609
|
const { cache } = options;
|
|
5591
5610
|
if (!cache) return Array.from(await requestEmbedding(text14, options, outer));
|
|
5611
|
+
const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5592
5612
|
const cached = cache.get(text14);
|
|
5593
|
-
|
|
5613
|
+
const cachedModel = cached && cachedEmbeddingModels.get(cached);
|
|
5614
|
+
if (cached && (cachedModel === void 0 || cachedModel === model)) return Array.from(cached);
|
|
5594
5615
|
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
5595
5616
|
inFlightByCache.set(cache, inFlight);
|
|
5596
|
-
const
|
|
5617
|
+
const requestKey = JSON.stringify([model, text14]);
|
|
5618
|
+
const pending = inFlight.get(requestKey);
|
|
5597
5619
|
if (pending) {
|
|
5598
5620
|
try {
|
|
5599
5621
|
return Array.from(await pending);
|
|
@@ -5602,13 +5624,14 @@ async function embedOne(text14, options, outer) {
|
|
|
5602
5624
|
}
|
|
5603
5625
|
}
|
|
5604
5626
|
const request = requestEmbedding(text14, options, outer);
|
|
5605
|
-
inFlight.set(
|
|
5627
|
+
inFlight.set(requestKey, request);
|
|
5606
5628
|
try {
|
|
5607
5629
|
const embedding2 = await request;
|
|
5630
|
+
cachedEmbeddingModels.set(embedding2, model);
|
|
5608
5631
|
cache.set(text14, embedding2);
|
|
5609
5632
|
return Array.from(embedding2);
|
|
5610
5633
|
} finally {
|
|
5611
|
-
if (inFlight.get(
|
|
5634
|
+
if (inFlight.get(requestKey) === request) inFlight.delete(requestKey);
|
|
5612
5635
|
}
|
|
5613
5636
|
}
|
|
5614
5637
|
async function requestEmbedding(text14, options, outer) {
|
|
@@ -5691,13 +5714,15 @@ async function embedMany(texts, options, outer) {
|
|
|
5691
5714
|
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
5692
5715
|
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
5693
5716
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
5717
|
+
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5694
5718
|
const results = new Array(texts.length).fill(null);
|
|
5695
5719
|
const uncachedIndices = [];
|
|
5696
5720
|
const uncachedTexts = [];
|
|
5697
5721
|
for (let i = 0; i < texts.length; i++) {
|
|
5698
5722
|
if (cache) {
|
|
5699
5723
|
const cached = cache.get(texts[i]);
|
|
5700
|
-
|
|
5724
|
+
const cachedModel = cached && cachedEmbeddingModels.get(cached);
|
|
5725
|
+
if (cached && (cachedModel === void 0 || cachedModel === embeddingModel)) {
|
|
5701
5726
|
results[i] = Array.from(cached);
|
|
5702
5727
|
continue;
|
|
5703
5728
|
}
|
|
@@ -5713,7 +5738,6 @@ async function embedMany(texts, options, outer) {
|
|
|
5713
5738
|
...taskTypeHeader(options.taskType)
|
|
5714
5739
|
};
|
|
5715
5740
|
if (outer?.aborted) throw outer.reason;
|
|
5716
|
-
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5717
5741
|
let newEmbeddings;
|
|
5718
5742
|
if (uncachedTexts.length <= chunkSize) {
|
|
5719
5743
|
newEmbeddings = await generateEmbeddingsBatch(
|
|
@@ -5761,6 +5785,7 @@ async function embedMany(texts, options, outer) {
|
|
|
5761
5785
|
const f32Embedding = Float32Array.from(newEmbeddings[i]);
|
|
5762
5786
|
results[uncachedIndices[i]] = Array.from(f32Embedding);
|
|
5763
5787
|
if (cache) {
|
|
5788
|
+
cachedEmbeddingModels.set(f32Embedding, embeddingModel);
|
|
5764
5789
|
cache.set(uncachedTexts[i], f32Embedding);
|
|
5765
5790
|
}
|
|
5766
5791
|
}
|
|
@@ -5885,6 +5910,37 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
|
|
|
5885
5910
|
}));
|
|
5886
5911
|
return updateMessageChunksOp(ctx, messageId, messageChunks, embeddingModel);
|
|
5887
5912
|
}
|
|
5913
|
+
var MIN_SEALED_EMBEDDING_HEX = 256;
|
|
5914
|
+
function rawHasEmbedding(value) {
|
|
5915
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
5916
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
5917
|
+
if (isEncrypted(value)) {
|
|
5918
|
+
return value.length - value.indexOf(":", 4) - 1 >= MIN_SEALED_EMBEDDING_HEX;
|
|
5919
|
+
}
|
|
5920
|
+
try {
|
|
5921
|
+
const parsed = JSON.parse(value);
|
|
5922
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
5923
|
+
} catch {
|
|
5924
|
+
return false;
|
|
5925
|
+
}
|
|
5926
|
+
}
|
|
5927
|
+
function sealedVersion(value) {
|
|
5928
|
+
if (typeof value !== "string" || !isEncrypted(value)) return null;
|
|
5929
|
+
return value.startsWith("enc:v2:") ? "v2" : "v3";
|
|
5930
|
+
}
|
|
5931
|
+
function mayNeedChunkEmbedding(raw, embeddingModel, filter) {
|
|
5932
|
+
const role = raw.role;
|
|
5933
|
+
if (role === "system") return false;
|
|
5934
|
+
if (filter?.roles && !filter.roles.includes(role ?? "")) return false;
|
|
5935
|
+
if (isNonEmbeddableOrigin(raw.origin, filter?.reembedDiscarded)) {
|
|
5936
|
+
return false;
|
|
5937
|
+
}
|
|
5938
|
+
const model = raw.embedding_model;
|
|
5939
|
+
if (typeof model === "string" && model !== embeddingModel) return true;
|
|
5940
|
+
if (rawHasEmbedding(raw.chunks)) return false;
|
|
5941
|
+
if (rawHasEmbedding(raw.vector) && !filter?.rechunkExisting) return false;
|
|
5942
|
+
return true;
|
|
5943
|
+
}
|
|
5888
5944
|
async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
5889
5945
|
const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5890
5946
|
const { chunkSize = DEFAULT_CHUNK_SIZE } = options;
|
|
@@ -5897,11 +5953,31 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
5897
5953
|
let considered = 0;
|
|
5898
5954
|
let sealedRowsSeen = 0;
|
|
5899
5955
|
let rowsSeen = 0;
|
|
5956
|
+
const keptSealed = /* @__PURE__ */ new Map();
|
|
5957
|
+
const candidatesStillSealed = /* @__PURE__ */ new Map();
|
|
5958
|
+
const droppedSealed = /* @__PURE__ */ new Map();
|
|
5959
|
+
const rawFilter = (raw) => {
|
|
5960
|
+
rowsSeen++;
|
|
5961
|
+
const keep = mayNeedChunkEmbedding(raw, embeddingModel, filter);
|
|
5962
|
+
const version = sealedVersion(raw.content);
|
|
5963
|
+
if (!version) return keep;
|
|
5964
|
+
if (keep) {
|
|
5965
|
+
keptSealed.set(version, (keptSealed.get(version) ?? 0) + 1);
|
|
5966
|
+
} else {
|
|
5967
|
+
const dropped = droppedSealed.get(version);
|
|
5968
|
+
if (dropped) dropped.count++;
|
|
5969
|
+
else droppedSealed.set(version, { count: 1, probeId: raw.id });
|
|
5970
|
+
}
|
|
5971
|
+
return keep;
|
|
5972
|
+
};
|
|
5900
5973
|
for (const conv of targetConversations) {
|
|
5901
|
-
const messages = await getMessagesOp(ctx, conv.conversationId);
|
|
5974
|
+
const messages = await getMessagesOp(ctx, conv.conversationId, { rawFilter });
|
|
5902
5975
|
for (const message of messages) {
|
|
5903
|
-
|
|
5904
|
-
if (
|
|
5976
|
+
const stillSealed = sealedVersion(message.content);
|
|
5977
|
+
if (stillSealed) {
|
|
5978
|
+
sealedRowsSeen++;
|
|
5979
|
+
candidatesStillSealed.set(stillSealed, (candidatesStillSealed.get(stillSealed) ?? 0) + 1);
|
|
5980
|
+
}
|
|
5905
5981
|
const isStale = message.embeddingModel !== void 0 && message.embeddingModel !== null && message.embeddingModel !== embeddingModel;
|
|
5906
5982
|
if (message.chunks && message.chunks.length > 0 && !isStale) continue;
|
|
5907
5983
|
const hasVector = message.vector && message.vector.length > 0;
|
|
@@ -5914,6 +5990,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
5914
5990
|
stillEncrypted++;
|
|
5915
5991
|
continue;
|
|
5916
5992
|
}
|
|
5993
|
+
if (isToolResultsRow(message)) continue;
|
|
5917
5994
|
if (message.content.length < minLength) continue;
|
|
5918
5995
|
if (shouldChunkMessage(message.content, chunkSize)) {
|
|
5919
5996
|
longMessages.push({
|
|
@@ -5925,6 +6002,12 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
5925
6002
|
}
|
|
5926
6003
|
}
|
|
5927
6004
|
}
|
|
6005
|
+
for (const [version, dropped] of droppedSealed) {
|
|
6006
|
+
const keyOpenedACandidate = (keptSealed.get(version) ?? 0) > (candidatesStillSealed.get(version) ?? 0);
|
|
6007
|
+
if (keyOpenedACandidate) continue;
|
|
6008
|
+
const probe = await getMessageOp(ctx, dropped.probeId);
|
|
6009
|
+
if (!probe || isEncrypted(probe.content)) sealedRowsSeen += dropped.count;
|
|
6010
|
+
}
|
|
5928
6011
|
if (stillEncrypted > 0 || sealedRowsSeen > 0) {
|
|
5929
6012
|
getLogger().error(
|
|
5930
6013
|
"memoryEngine: messages still encrypted (key unavailable?) \u2014 excluded from embedding",
|
|
@@ -11144,7 +11227,7 @@ var MaskScopedEmbeddingCache = class extends Map {
|
|
|
11144
11227
|
return this;
|
|
11145
11228
|
}
|
|
11146
11229
|
};
|
|
11147
|
-
var scopedViews =
|
|
11230
|
+
var { scopedViews } = getEmbeddingCacheState();
|
|
11148
11231
|
function maskScopedEmbeddingCache(cache, masked) {
|
|
11149
11232
|
const views = scopedViews.get(cache) ?? {};
|
|
11150
11233
|
scopedViews.set(cache, views);
|
|
@@ -12639,6 +12722,11 @@ init_logger();
|
|
|
12639
12722
|
|
|
12640
12723
|
// src/lib/db/entities/operations.ts
|
|
12641
12724
|
var import_watermelondb19 = require("@nozbe/watermelondb");
|
|
12725
|
+
async function assertCanWrite(ctx) {
|
|
12726
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
12727
|
+
throw new Error("Memory source is no longer eligible");
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12642
12730
|
function entityToStored(e) {
|
|
12643
12731
|
return {
|
|
12644
12732
|
uniqueId: e.id,
|
|
@@ -12779,6 +12867,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
12779
12867
|
let skipped = false;
|
|
12780
12868
|
let entities = [];
|
|
12781
12869
|
await ctx.database.write(async () => {
|
|
12870
|
+
await assertCanWrite(ctx);
|
|
12782
12871
|
const {
|
|
12783
12872
|
entities: byName,
|
|
12784
12873
|
operations: entityOps,
|
|
@@ -12854,6 +12943,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
12854
12943
|
let skipped = false;
|
|
12855
12944
|
let entities = [];
|
|
12856
12945
|
await ctx.database.write(async () => {
|
|
12946
|
+
await assertCanWrite(ctx);
|
|
12857
12947
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
12858
12948
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
12859
12949
|
skipped = true;
|
|
@@ -12914,6 +13004,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
12914
13004
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("memory_id", import_watermelondb19.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
12915
13005
|
if (links.length === 0) return;
|
|
12916
13006
|
await ctx.database.write(async () => {
|
|
13007
|
+
await assertCanWrite(ctx);
|
|
12917
13008
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
12918
13009
|
});
|
|
12919
13010
|
}
|
|
@@ -12922,6 +13013,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
12922
13013
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("user_id", userId)).fetch();
|
|
12923
13014
|
if (links.length === 0) return;
|
|
12924
13015
|
await ctx.database.write(async () => {
|
|
13016
|
+
await assertCanWrite(ctx);
|
|
12925
13017
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
12926
13018
|
});
|
|
12927
13019
|
}
|
|
@@ -13086,6 +13178,11 @@ function visibilityConditions(requested) {
|
|
|
13086
13178
|
function isKinded(record2) {
|
|
13087
13179
|
return record2.kind !== null && record2.kind !== void 0;
|
|
13088
13180
|
}
|
|
13181
|
+
async function assertCanWrite2(ctx) {
|
|
13182
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
13183
|
+
throw new Error("Memory source is no longer eligible");
|
|
13184
|
+
}
|
|
13185
|
+
}
|
|
13089
13186
|
function assertValidKindLevel(kind, level) {
|
|
13090
13187
|
const hasKind = kind !== null && kind !== void 0;
|
|
13091
13188
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -13266,8 +13363,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
13266
13363
|
ctx.embeddedWalletSigner
|
|
13267
13364
|
) : opts.content;
|
|
13268
13365
|
const created = await ctx.database.write(async () => {
|
|
13269
|
-
|
|
13270
|
-
throw new Error("Memory source is no longer eligible");
|
|
13366
|
+
await assertCanWrite2(ctx);
|
|
13271
13367
|
return ctx.vaultMemoryCollection.create(
|
|
13272
13368
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
|
|
13273
13369
|
);
|
|
@@ -13286,8 +13382,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
13286
13382
|
) : opts.content;
|
|
13287
13383
|
let createdRecord = null;
|
|
13288
13384
|
await ctx.database.write(async () => {
|
|
13289
|
-
|
|
13290
|
-
throw new Error("Memory source is no longer eligible");
|
|
13385
|
+
await assertCanWrite2(ctx);
|
|
13291
13386
|
let target;
|
|
13292
13387
|
try {
|
|
13293
13388
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -13379,8 +13474,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
13379
13474
|
})
|
|
13380
13475
|
);
|
|
13381
13476
|
const created = await ctx.database.write(async () => {
|
|
13382
|
-
|
|
13383
|
-
throw new Error("Memory source is no longer eligible");
|
|
13477
|
+
await assertCanWrite2(ctx);
|
|
13384
13478
|
const prepared = optionsArray.map(
|
|
13385
13479
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
13386
13480
|
(record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -13685,8 +13779,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13685
13779
|
const record2 = probe;
|
|
13686
13780
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13687
13781
|
await ctx.database.write(async () => {
|
|
13688
|
-
|
|
13689
|
-
throw new Error("Memory source is no longer eligible");
|
|
13782
|
+
await assertCanWrite2(ctx);
|
|
13690
13783
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
13691
13784
|
stale = true;
|
|
13692
13785
|
return;
|
|
@@ -13797,6 +13890,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
13797
13890
|
let stale = false;
|
|
13798
13891
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13799
13892
|
await ctx.database.write(async (writer) => {
|
|
13893
|
+
await assertCanWrite2(ctx);
|
|
13800
13894
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13801
13895
|
stale = true;
|
|
13802
13896
|
return;
|
|
@@ -13838,6 +13932,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
13838
13932
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
13839
13933
|
let cleared = false;
|
|
13840
13934
|
await ctx.database.write(async () => {
|
|
13935
|
+
await assertCanWrite2(ctx);
|
|
13841
13936
|
if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
|
|
13842
13937
|
cleared = true;
|
|
13843
13938
|
await record2.update((r) => {
|
|
@@ -13861,6 +13956,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
13861
13956
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
|
|
13862
13957
|
let stale = false;
|
|
13863
13958
|
await ctx.database.write(async () => {
|
|
13959
|
+
await assertCanWrite2(ctx);
|
|
13864
13960
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13865
13961
|
stale = true;
|
|
13866
13962
|
return;
|
|
@@ -13889,6 +13985,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
13889
13985
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
13890
13986
|
let stale = false;
|
|
13891
13987
|
await ctx.database.write(async () => {
|
|
13988
|
+
await assertCanWrite2(ctx);
|
|
13892
13989
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
13893
13990
|
stale = true;
|
|
13894
13991
|
return;
|
|
@@ -13926,8 +14023,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
13926
14023
|
}
|
|
13927
14024
|
let stale = false;
|
|
13928
14025
|
await ctx.database.write(async () => {
|
|
13929
|
-
|
|
13930
|
-
throw new Error("Memory source is no longer eligible");
|
|
14026
|
+
await assertCanWrite2(ctx);
|
|
13931
14027
|
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
|
|
13932
14028
|
stale = true;
|
|
13933
14029
|
return;
|
|
@@ -14089,6 +14185,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
14089
14185
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
14090
14186
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
14091
14187
|
await ctx.database.write(async () => {
|
|
14188
|
+
await assertCanWrite2(ctx);
|
|
14092
14189
|
const records = [];
|
|
14093
14190
|
for (const id of chunkIds) {
|
|
14094
14191
|
try {
|
|
@@ -14122,6 +14219,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14122
14219
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
14123
14220
|
try {
|
|
14124
14221
|
await ctx.database.write(async (writer) => {
|
|
14222
|
+
await assertCanWrite2(ctx);
|
|
14125
14223
|
let record2;
|
|
14126
14224
|
try {
|
|
14127
14225
|
record2 = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -14152,6 +14250,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14152
14250
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
14153
14251
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
14154
14252
|
await ctx.database.write(async () => {
|
|
14253
|
+
await assertCanWrite2(ctx);
|
|
14155
14254
|
const writes = [];
|
|
14156
14255
|
for (const id of chunkIds) {
|
|
14157
14256
|
let record2;
|
|
@@ -14184,6 +14283,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
14184
14283
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb20.Q.where("user_id", userId), import_watermelondb20.Q.where("is_deleted", false)).fetch();
|
|
14185
14284
|
if (records.length === 0) return 0;
|
|
14186
14285
|
await ctx.database.write(async () => {
|
|
14286
|
+
await assertCanWrite2(ctx);
|
|
14187
14287
|
const prepared = records.map(
|
|
14188
14288
|
(record2) => record2.prepareUpdate((r) => {
|
|
14189
14289
|
r._setRaw("is_deleted", true);
|
|
@@ -14238,6 +14338,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
14238
14338
|
let stale = false;
|
|
14239
14339
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
14240
14340
|
await ctx.database.write(async () => {
|
|
14341
|
+
await assertCanWrite2(ctx);
|
|
14241
14342
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
|
|
14242
14343
|
stale = true;
|
|
14243
14344
|
return;
|
|
@@ -14261,6 +14362,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
14261
14362
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
|
|
14262
14363
|
let stale = false;
|
|
14263
14364
|
await ctx.database.write(async () => {
|
|
14365
|
+
await assertCanWrite2(ctx);
|
|
14264
14366
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
|
|
14265
14367
|
stale = true;
|
|
14266
14368
|
return;
|
|
@@ -14281,6 +14383,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
14281
14383
|
const now = opts.now ?? Date.now();
|
|
14282
14384
|
let stale = false;
|
|
14283
14385
|
await ctx.database.write(async () => {
|
|
14386
|
+
await assertCanWrite2(ctx);
|
|
14284
14387
|
const archivedAt = record2.archivedAt;
|
|
14285
14388
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
14286
14389
|
stale = true;
|
|
@@ -14320,6 +14423,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
|
|
|
14320
14423
|
}
|
|
14321
14424
|
let written = false;
|
|
14322
14425
|
await ctx.database.write(async () => {
|
|
14426
|
+
await assertCanWrite2(ctx);
|
|
14323
14427
|
if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
|
|
14324
14428
|
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14325
14429
|
if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
|
|
@@ -17856,6 +17960,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
17856
17960
|
).map((c) => c.candidate);
|
|
17857
17961
|
}
|
|
17858
17962
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
17963
|
+
const { memoryStore, signal } = options;
|
|
17964
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
17965
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
17966
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
17967
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
17968
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
17969
|
+
signal?.throwIfAborted();
|
|
17859
17970
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
17860
17971
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
17861
17972
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -17889,6 +18000,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17889
18000
|
}
|
|
17890
18001
|
});
|
|
17891
18002
|
const extractMs = Date.now() - tExtract;
|
|
18003
|
+
signal?.throwIfAborted();
|
|
17892
18004
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
17893
18005
|
const log = getLogger();
|
|
17894
18006
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -17936,16 +18048,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17936
18048
|
const results = [];
|
|
17937
18049
|
const quarantinedInfo = [];
|
|
17938
18050
|
let failedWrites = 0;
|
|
18051
|
+
let auditRows;
|
|
17939
18052
|
const tRetain = Date.now();
|
|
17940
18053
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
17941
18054
|
try {
|
|
18055
|
+
signal?.throwIfAborted();
|
|
17942
18056
|
if (isQuarantined) {
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
18057
|
+
let existingId;
|
|
18058
|
+
if (memoryStore) {
|
|
18059
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
18060
|
+
scopes: [options.scope ?? "private"],
|
|
18061
|
+
includeArchived: true,
|
|
18062
|
+
includeQuarantined: true,
|
|
18063
|
+
includeSuperseded: true
|
|
18064
|
+
}));
|
|
18065
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
18066
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
18067
|
+
existingId = (await auditRows).find(
|
|
18068
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
18069
|
+
)?.uniqueId ?? null;
|
|
18070
|
+
} else {
|
|
18071
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
18072
|
+
retainCtx.vaultCtx,
|
|
18073
|
+
candidate.content,
|
|
18074
|
+
candidate.sourceMessageIds,
|
|
18075
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
18076
|
+
).catch(() => null);
|
|
18077
|
+
}
|
|
17949
18078
|
if (existingId) {
|
|
17950
18079
|
quarantinedInfo.push({
|
|
17951
18080
|
candidate,
|
|
@@ -17956,18 +18085,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17956
18085
|
continue;
|
|
17957
18086
|
}
|
|
17958
18087
|
}
|
|
17959
|
-
const
|
|
18088
|
+
const retainOptions = {
|
|
17960
18089
|
source: "auto-extracted",
|
|
17961
18090
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
17962
18091
|
respectTombstones: true,
|
|
17963
18092
|
...options.scope !== void 0 && { scope: options.scope },
|
|
17964
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
17965
18093
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
17966
18094
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
17967
18095
|
factType: candidate.type,
|
|
17968
18096
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
18097
|
+
};
|
|
18098
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
18099
|
+
...retainOptions,
|
|
18100
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
18101
|
+
signal
|
|
18102
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
18103
|
+
...retainOptions,
|
|
18104
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
17969
18105
|
});
|
|
17970
18106
|
if (isQuarantined) {
|
|
18107
|
+
auditRows = void 0;
|
|
17971
18108
|
const info = {
|
|
17972
18109
|
candidate,
|
|
17973
18110
|
memoryId: result.memoryId,
|
|
@@ -17986,9 +18123,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17986
18123
|
}
|
|
17987
18124
|
succeededCandidates.push(candidate);
|
|
17988
18125
|
results.push(result);
|
|
17989
|
-
if (result.action !== "suppressed" &&
|
|
18126
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
17990
18127
|
try {
|
|
17991
|
-
|
|
18128
|
+
signal?.throwIfAborted();
|
|
18129
|
+
if (memoryStore) {
|
|
18130
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
18131
|
+
unlessUserManaged: true,
|
|
18132
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
18133
|
+
signal
|
|
18134
|
+
});
|
|
18135
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
17992
18136
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
17993
18137
|
unlessTopicsUserManaged: true
|
|
17994
18138
|
});
|
|
@@ -18238,7 +18382,7 @@ function createAutoExtractor(options) {
|
|
|
18238
18382
|
};
|
|
18239
18383
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
18240
18384
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
18241
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
18385
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
18242
18386
|
getLogger().warn(
|
|
18243
18387
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
18244
18388
|
);
|
|
@@ -18283,6 +18427,8 @@ function createAutoExtractor(options) {
|
|
|
18283
18427
|
try {
|
|
18284
18428
|
const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
18285
18429
|
extract,
|
|
18430
|
+
memoryStore: options.memoryStore,
|
|
18431
|
+
signal: options.signal,
|
|
18286
18432
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
18287
18433
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
18288
18434
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -19342,44 +19488,48 @@ async function recall(query, ctx, options = {}) {
|
|
|
19342
19488
|
embeddingOptions,
|
|
19343
19489
|
ctx.vaultCache,
|
|
19344
19490
|
searchOptions
|
|
19345
|
-
)))(
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19363
|
-
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
|
|
19491
|
+
)))(
|
|
19492
|
+
query,
|
|
19493
|
+
{
|
|
19494
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
19495
|
+
minSimilarity: vaultMinScore,
|
|
19496
|
+
useFusion: true,
|
|
19497
|
+
rerank: flags.rerank,
|
|
19498
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
19499
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
19500
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
19501
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
19502
|
+
},
|
|
19503
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
19504
|
+
...options.recency && { recency: options.recency },
|
|
19505
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
19506
|
+
...options.supersessionBoost !== void 0 && {
|
|
19507
|
+
supersessionBoost: options.supersessionBoost
|
|
19508
|
+
},
|
|
19509
|
+
...options.supersessionWindow !== void 0 && {
|
|
19510
|
+
supersessionWindow: options.supersessionWindow
|
|
19511
|
+
},
|
|
19512
|
+
...options.proofCountAlpha !== void 0 && {
|
|
19513
|
+
proofCountAlpha: options.proofCountAlpha
|
|
19514
|
+
},
|
|
19515
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
19516
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
19517
|
+
},
|
|
19518
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
19519
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
19520
|
+
...subQueries && { subQueries },
|
|
19521
|
+
...options.scopes && { scopes: options.scopes },
|
|
19522
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
19523
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
19524
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
19525
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
19526
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
19527
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
19528
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
19529
|
+
queryEmbedTotalTimeoutMs
|
|
19369
19530
|
},
|
|
19370
|
-
|
|
19371
|
-
|
|
19372
|
-
...subQueries && { subQueries },
|
|
19373
|
-
...options.scopes && { scopes: options.scopes },
|
|
19374
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
19375
|
-
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
19376
|
-
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
19377
|
-
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
19378
|
-
...entityRanking.length > 0 && { entityRanking },
|
|
19379
|
-
...temporalRanking.length > 0 && { temporalRanking },
|
|
19380
|
-
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
19381
|
-
queryEmbedTotalTimeoutMs
|
|
19382
|
-
});
|
|
19531
|
+
options.embeddingCache
|
|
19532
|
+
);
|
|
19383
19533
|
factResults.push(
|
|
19384
19534
|
...dedupeBy(
|
|
19385
19535
|
results,
|
|
@@ -20384,6 +20534,7 @@ function createLocalMemoryStore(options) {
|
|
|
20384
20534
|
database,
|
|
20385
20535
|
entityCollection: database.get("entity"),
|
|
20386
20536
|
memoryEntityCollection: database.get("memory_entity"),
|
|
20537
|
+
canWrite: options.canWrite,
|
|
20387
20538
|
...userId !== void 0 && { userId },
|
|
20388
20539
|
...options.allowUnscopedRows !== void 0 && {
|
|
20389
20540
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -20395,10 +20546,21 @@ function createLocalMemoryStore(options) {
|
|
|
20395
20546
|
walletAddress: options.walletAddress,
|
|
20396
20547
|
signMessage: options.signMessage,
|
|
20397
20548
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
20549
|
+
canWrite: options.canWrite,
|
|
20398
20550
|
...userId !== void 0 && { userId },
|
|
20399
20551
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
20400
20552
|
entityCtx
|
|
20401
20553
|
};
|
|
20554
|
+
const assertWrite = async (writeOptions) => {
|
|
20555
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20556
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
20557
|
+
throw new Error("Memory source is no longer eligible");
|
|
20558
|
+
}
|
|
20559
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
20560
|
+
throw new Error("Memory source is no longer eligible");
|
|
20561
|
+
}
|
|
20562
|
+
writeOptions?.signal?.throwIfAborted();
|
|
20563
|
+
};
|
|
20402
20564
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
20403
20565
|
const ownedBy = userId !== void 0 ? [import_watermelondb23.Q.where("user_id", userId)] : [];
|
|
20404
20566
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb23.Q.or(import_watermelondb23.Q.where("user_id", userId), import_watermelondb23.Q.where("user_id", null))] : [import_watermelondb23.Q.where("user_id", userId)];
|
|
@@ -20510,9 +20672,25 @@ function createLocalMemoryStore(options) {
|
|
|
20510
20672
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
20511
20673
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
20512
20674
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
20513
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
20675
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
20676
|
+
await assertWrite(writeOptions);
|
|
20514
20677
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb23.Q.where("id", memoryId), import_watermelondb23.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
20515
|
-
return owned > 0 ? writer.callWriter(
|
|
20678
|
+
return owned > 0 ? writer.callWriter(
|
|
20679
|
+
() => linkMemoryEntitiesOp(
|
|
20680
|
+
{
|
|
20681
|
+
...entityCtx,
|
|
20682
|
+
canWrite: async () => {
|
|
20683
|
+
await assertWrite(writeOptions);
|
|
20684
|
+
return true;
|
|
20685
|
+
}
|
|
20686
|
+
},
|
|
20687
|
+
memoryId,
|
|
20688
|
+
topics,
|
|
20689
|
+
{
|
|
20690
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
20691
|
+
}
|
|
20692
|
+
)
|
|
20693
|
+
) : [];
|
|
20516
20694
|
}),
|
|
20517
20695
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
20518
20696
|
recall: (query, recallOptions) => recall(
|
|
@@ -20522,14 +20700,33 @@ function createLocalMemoryStore(options) {
|
|
|
20522
20700
|
),
|
|
20523
20701
|
retain: (content, retainOptions) => retain(
|
|
20524
20702
|
content,
|
|
20525
|
-
{
|
|
20703
|
+
{
|
|
20704
|
+
vaultCtx: {
|
|
20705
|
+
...vaultCtx,
|
|
20706
|
+
canWrite: async () => {
|
|
20707
|
+
await assertWrite(retainOptions);
|
|
20708
|
+
return true;
|
|
20709
|
+
}
|
|
20710
|
+
},
|
|
20711
|
+
embeddingOptions: options.embeddingOptions,
|
|
20712
|
+
vaultCache
|
|
20713
|
+
},
|
|
20526
20714
|
retainOptions
|
|
20527
20715
|
),
|
|
20528
20716
|
factSource: {
|
|
20529
|
-
search: (query, searchOptions) => searchVaultMemoriesWithSize(
|
|
20717
|
+
search: (query, searchOptions, embeddingCache) => searchVaultMemoriesWithSize(
|
|
20530
20718
|
query,
|
|
20531
20719
|
vaultCtx,
|
|
20532
|
-
{
|
|
20720
|
+
{
|
|
20721
|
+
...options.embeddingOptions,
|
|
20722
|
+
taskType: "memory_recall_embed",
|
|
20723
|
+
...embeddingCache && !options.embeddingOptions.cache && {
|
|
20724
|
+
cache: maskScopedEmbeddingCache(
|
|
20725
|
+
embeddingCache,
|
|
20726
|
+
Boolean(options.embeddingOptions.maskInput)
|
|
20727
|
+
)
|
|
20728
|
+
}
|
|
20729
|
+
},
|
|
20533
20730
|
vaultCache,
|
|
20534
20731
|
searchOptions
|
|
20535
20732
|
),
|
|
@@ -21161,7 +21358,14 @@ function stored(row) {
|
|
|
21161
21358
|
function createRemoteMemoryPipeline(options) {
|
|
21162
21359
|
const { persistence, embeddingOptions } = options;
|
|
21163
21360
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21164
|
-
const operation = (mode) => {
|
|
21361
|
+
const operation = (mode, queryOptions = embeddingOptions, writeOptions) => {
|
|
21362
|
+
const signal = writeOptions?.signal;
|
|
21363
|
+
const assertWrite = async () => {
|
|
21364
|
+
signal?.throwIfAborted();
|
|
21365
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
21366
|
+
throw new Error("Memory source is no longer eligible");
|
|
21367
|
+
signal?.throwIfAborted();
|
|
21368
|
+
};
|
|
21165
21369
|
const rejectUndecryptable = (failed) => {
|
|
21166
21370
|
if (!failed.length) return;
|
|
21167
21371
|
if (mode === "retain")
|
|
@@ -21179,7 +21383,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21179
21383
|
return items.map((item) => stored(item.memory));
|
|
21180
21384
|
};
|
|
21181
21385
|
const get = async (id) => {
|
|
21182
|
-
const snapshot = snapshots.get(id) ?? await persistence.get(id);
|
|
21386
|
+
const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
21183
21387
|
if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
|
|
21184
21388
|
snapshots.set(id, snapshot);
|
|
21185
21389
|
return stored(snapshot.memory);
|
|
@@ -21192,7 +21396,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21192
21396
|
const start = Date.now();
|
|
21193
21397
|
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
21194
21398
|
const embed = (texts) => generateEmbeddings(texts, {
|
|
21195
|
-
...
|
|
21399
|
+
...queryOptions,
|
|
21196
21400
|
taskType: mode === "retain" ? "memory_retain_embed" : "memory_recall_embed",
|
|
21197
21401
|
totalTimeoutMs: budgetMs
|
|
21198
21402
|
});
|
|
@@ -21212,7 +21416,11 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21212
21416
|
}
|
|
21213
21417
|
};
|
|
21214
21418
|
const [primary, facetEmbeddings] = await Promise.all([
|
|
21215
|
-
search.queryEmbedding ??
|
|
21419
|
+
search.queryEmbedding ?? (mode === "recall" && queryOptions.cache ? generateEmbedding(query, {
|
|
21420
|
+
...queryOptions,
|
|
21421
|
+
taskType: "memory_recall_embed",
|
|
21422
|
+
totalTimeoutMs: budgetMs
|
|
21423
|
+
}) : embed([query]).then((vectors2) => vectors2[0])),
|
|
21216
21424
|
embedFacets()
|
|
21217
21425
|
]);
|
|
21218
21426
|
const queryEmbedding = storedVector(primary);
|
|
@@ -21225,7 +21433,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21225
21433
|
if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
|
|
21226
21434
|
}
|
|
21227
21435
|
const forceIds = [...forced];
|
|
21228
|
-
const windowOptions = (i,
|
|
21436
|
+
const windowOptions = (i, signal2) => ({
|
|
21229
21437
|
limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
|
|
21230
21438
|
force_ids: i === 0 ? forceIds : [],
|
|
21231
21439
|
...search.scopes && { scopes: search.scopes },
|
|
@@ -21233,13 +21441,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21233
21441
|
...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
|
|
21234
21442
|
include_archived: search.includeArchived,
|
|
21235
21443
|
embedding_model: model,
|
|
21236
|
-
...
|
|
21444
|
+
...signal2 && { signal: signal2 }
|
|
21237
21445
|
});
|
|
21238
21446
|
const vectors = [queryEmbedding, ...facetEmbeddings];
|
|
21239
21447
|
let windows;
|
|
21240
21448
|
if (mode === "retain") {
|
|
21241
21449
|
windows = await Promise.all(
|
|
21242
|
-
vectors.map(
|
|
21450
|
+
vectors.map(
|
|
21451
|
+
(embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
|
|
21452
|
+
)
|
|
21243
21453
|
);
|
|
21244
21454
|
} else {
|
|
21245
21455
|
const deadline = new AbortController();
|
|
@@ -21327,12 +21537,15 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21327
21537
|
twin_opt_in: false
|
|
21328
21538
|
};
|
|
21329
21539
|
};
|
|
21330
|
-
const write = async (memory, snapshot) =>
|
|
21540
|
+
const write = async (memory, snapshot) => {
|
|
21541
|
+
await assertWrite();
|
|
21542
|
+
return remember([await persistence.put(memory, snapshot, signal)])[0];
|
|
21543
|
+
};
|
|
21331
21544
|
const port = {
|
|
21332
21545
|
prepare,
|
|
21333
21546
|
get,
|
|
21334
21547
|
getFresh: async (id) => {
|
|
21335
|
-
const current = await persistence.get(id);
|
|
21548
|
+
const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
|
|
21336
21549
|
return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
|
|
21337
21550
|
},
|
|
21338
21551
|
tombstones: async (embedding2, embeddingModel, scope, folderId) => {
|
|
@@ -21343,7 +21556,8 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21343
21556
|
embedding_model: embeddingModel,
|
|
21344
21557
|
strict_model: true,
|
|
21345
21558
|
include_deleted: true,
|
|
21346
|
-
deleted_only: true
|
|
21559
|
+
deleted_only: true,
|
|
21560
|
+
signal
|
|
21347
21561
|
});
|
|
21348
21562
|
rejectUndecryptable(window2.failed);
|
|
21349
21563
|
return remember(window2.items);
|
|
@@ -21399,14 +21613,18 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21399
21613
|
if (!target || !newer || id === successor) return false;
|
|
21400
21614
|
const old = snapshots.get(id);
|
|
21401
21615
|
const next = snapshots.get(successor);
|
|
21616
|
+
await assertWrite();
|
|
21402
21617
|
remember(
|
|
21403
|
-
await persistence.putMany(
|
|
21404
|
-
|
|
21405
|
-
|
|
21406
|
-
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21618
|
+
await persistence.putMany(
|
|
21619
|
+
[
|
|
21620
|
+
{
|
|
21621
|
+
memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
|
|
21622
|
+
expectedVersion: old
|
|
21623
|
+
},
|
|
21624
|
+
{ memory: next.memory, expectedVersion: next }
|
|
21625
|
+
],
|
|
21626
|
+
signal
|
|
21627
|
+
)
|
|
21410
21628
|
);
|
|
21411
21629
|
return true;
|
|
21412
21630
|
},
|
|
@@ -21415,18 +21633,22 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21415
21633
|
if (!target) return { created: null, retired: false };
|
|
21416
21634
|
const snapshot = snapshots.get(targetId);
|
|
21417
21635
|
const successor = createRow(input);
|
|
21636
|
+
await assertWrite();
|
|
21418
21637
|
const rows = remember(
|
|
21419
|
-
await persistence.putMany(
|
|
21420
|
-
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
|
|
21428
|
-
|
|
21429
|
-
|
|
21638
|
+
await persistence.putMany(
|
|
21639
|
+
[
|
|
21640
|
+
{ memory: successor, expectedVersion: 0 },
|
|
21641
|
+
{
|
|
21642
|
+
memory: {
|
|
21643
|
+
...snapshot.memory,
|
|
21644
|
+
superseded_by: successor.memory_id,
|
|
21645
|
+
superseded_at: Date.now()
|
|
21646
|
+
},
|
|
21647
|
+
expectedVersion: snapshot
|
|
21648
|
+
}
|
|
21649
|
+
],
|
|
21650
|
+
signal
|
|
21651
|
+
)
|
|
21430
21652
|
);
|
|
21431
21653
|
return { created: rows[0], retired: true };
|
|
21432
21654
|
}
|
|
@@ -21436,15 +21658,17 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21436
21658
|
const factSource = {
|
|
21437
21659
|
graphRanking: options.graphRanking,
|
|
21438
21660
|
temporalRanking: options.temporalRanking,
|
|
21439
|
-
search: async (text14, searchOptions) => {
|
|
21440
|
-
const
|
|
21661
|
+
search: async (text14, searchOptions, embeddingCache) => {
|
|
21662
|
+
const queryOptions = {
|
|
21663
|
+
...embeddingOptions,
|
|
21664
|
+
taskType: "memory_recall_embed",
|
|
21665
|
+
...embeddingCache && !embeddingOptions.cache && {
|
|
21666
|
+
cache: maskScopedEmbeddingCache(embeddingCache, Boolean(embeddingOptions.maskInput))
|
|
21667
|
+
}
|
|
21668
|
+
};
|
|
21669
|
+
const { prepare } = operation("recall", queryOptions);
|
|
21441
21670
|
const prepared = await prepare(text14, searchOptions);
|
|
21442
|
-
const ranked = await rankPreparedVaultCandidates(
|
|
21443
|
-
text14,
|
|
21444
|
-
prepared,
|
|
21445
|
-
{ ...embeddingOptions, taskType: "memory_recall_embed" },
|
|
21446
|
-
searchOptions
|
|
21447
|
-
);
|
|
21671
|
+
const ranked = await rankPreparedVaultCandidates(text14, prepared, queryOptions, searchOptions);
|
|
21448
21672
|
return {
|
|
21449
21673
|
...ranked,
|
|
21450
21674
|
rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
|
|
@@ -21459,7 +21683,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
21459
21683
|
factSource,
|
|
21460
21684
|
recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
|
|
21461
21685
|
retain: async (content, retainOptions) => {
|
|
21462
|
-
const { port } = operation("retain");
|
|
21686
|
+
const { port } = operation("retain", embeddingOptions, retainOptions);
|
|
21463
21687
|
return retainWithPersistence(
|
|
21464
21688
|
content,
|
|
21465
21689
|
{
|
|
@@ -22042,16 +22266,21 @@ function createRemoteMemoryStore(options) {
|
|
|
22042
22266
|
const record2 = await persistence.get(id);
|
|
22043
22267
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
22044
22268
|
};
|
|
22045
|
-
const mutateLocked = async (id, change, edit) => {
|
|
22046
|
-
|
|
22269
|
+
const mutateLocked = async (id, change, edit, writeOptions) => {
|
|
22270
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22271
|
+
const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
|
|
22047
22272
|
if (!record2) return null;
|
|
22273
|
+
if (record2.memory.is_deleted) return null;
|
|
22274
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
22275
|
+
throw new Error("Memory source is no longer eligible");
|
|
22276
|
+
writeOptions?.signal?.throwIfAborted();
|
|
22048
22277
|
const next = edit(structuredClone(record2.memory));
|
|
22049
22278
|
if (!next) return null;
|
|
22050
|
-
const saved = await persistence.put(next, record2);
|
|
22279
|
+
const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
|
|
22051
22280
|
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
22052
22281
|
return saved;
|
|
22053
22282
|
};
|
|
22054
|
-
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
22283
|
+
const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
|
|
22055
22284
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
22056
22285
|
const mutateMany = async (ids, change, edit) => {
|
|
22057
22286
|
const saved = /* @__PURE__ */ new Map();
|
|
@@ -22564,13 +22793,21 @@ function createRemoteMemoryStore(options) {
|
|
|
22564
22793
|
}))
|
|
22565
22794
|
);
|
|
22566
22795
|
},
|
|
22567
|
-
addTopics: async (memoryId, topics) => {
|
|
22796
|
+
addTopics: async (memoryId, topics, writeOptions) => {
|
|
22568
22797
|
const added = await withKnownKinds(topicInputs(topics, "auto"));
|
|
22569
|
-
const saved = await mutate(
|
|
22570
|
-
|
|
22571
|
-
|
|
22572
|
-
|
|
22573
|
-
|
|
22798
|
+
const saved = await mutate(
|
|
22799
|
+
memoryId,
|
|
22800
|
+
"edit",
|
|
22801
|
+
(memory) => {
|
|
22802
|
+
if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
|
|
22803
|
+
return {
|
|
22804
|
+
...memory,
|
|
22805
|
+
topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
|
|
22806
|
+
topics_updated_at: Date.now()
|
|
22807
|
+
};
|
|
22808
|
+
},
|
|
22809
|
+
writeOptions
|
|
22810
|
+
);
|
|
22574
22811
|
if (!saved) return [];
|
|
22575
22812
|
const now = /* @__PURE__ */ new Date();
|
|
22576
22813
|
return mergeTopics([], added).map(
|
|
@@ -23423,6 +23660,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23423
23660
|
};
|
|
23424
23661
|
const folderId = options.folderId ?? null;
|
|
23425
23662
|
let disposed = false;
|
|
23663
|
+
let activeBatch = null;
|
|
23426
23664
|
let running = false;
|
|
23427
23665
|
let wakeRequested = false;
|
|
23428
23666
|
let timer;
|
|
@@ -23459,14 +23697,18 @@ function createDurableAutoExtractor(options) {
|
|
|
23459
23697
|
}, delay);
|
|
23460
23698
|
}
|
|
23461
23699
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
23700
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
23462
23701
|
let watchdog;
|
|
23463
23702
|
let cancelled = false;
|
|
23703
|
+
const controller = new AbortController();
|
|
23704
|
+
activeBatch = controller;
|
|
23464
23705
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
23465
23706
|
try {
|
|
23466
23707
|
return await Promise.race([
|
|
23467
23708
|
new Promise((resolve, reject) => {
|
|
23468
23709
|
const worker = createAutoExtractor({
|
|
23469
23710
|
...options,
|
|
23711
|
+
signal: controller.signal,
|
|
23470
23712
|
retainCtx: {
|
|
23471
23713
|
...options.retainCtx,
|
|
23472
23714
|
vaultCtx: {
|
|
@@ -23495,6 +23737,8 @@ function createDurableAutoExtractor(options) {
|
|
|
23495
23737
|
]);
|
|
23496
23738
|
} finally {
|
|
23497
23739
|
cancelled = true;
|
|
23740
|
+
controller.abort();
|
|
23741
|
+
if (activeBatch === controller) activeBatch = null;
|
|
23498
23742
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
23499
23743
|
}
|
|
23500
23744
|
}
|
|
@@ -23506,6 +23750,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23506
23750
|
for (const message of loaded)
|
|
23507
23751
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
23508
23752
|
await database.write(async () => {
|
|
23753
|
+
if (disposed) return;
|
|
23509
23754
|
const current = idsOf(job);
|
|
23510
23755
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
23511
23756
|
if (!acknowledged.length) return;
|
|
@@ -23678,6 +23923,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23678
23923
|
jobScope,
|
|
23679
23924
|
jobFolderId
|
|
23680
23925
|
);
|
|
23926
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
23681
23927
|
options.onTurnComplete?.(result);
|
|
23682
23928
|
return result;
|
|
23683
23929
|
};
|
|
@@ -23714,6 +23960,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23714
23960
|
);
|
|
23715
23961
|
scheduleAfterSuccess = true;
|
|
23716
23962
|
} catch (error) {
|
|
23963
|
+
if (disposed) break;
|
|
23717
23964
|
attempts.set(job.id, attempted + 1);
|
|
23718
23965
|
retry = true;
|
|
23719
23966
|
reportError(error, conversationId);
|
|
@@ -23736,6 +23983,14 @@ function createDurableAutoExtractor(options) {
|
|
|
23736
23983
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
23737
23984
|
}
|
|
23738
23985
|
}
|
|
23986
|
+
function dispose() {
|
|
23987
|
+
disposed = true;
|
|
23988
|
+
activeBatch?.abort(options.signal?.reason);
|
|
23989
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
23990
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
23991
|
+
}
|
|
23992
|
+
if (options.signal?.aborted) dispose();
|
|
23993
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
23739
23994
|
schedule(0);
|
|
23740
23995
|
return {
|
|
23741
23996
|
processTurn(messages, conversationId) {
|
|
@@ -23815,10 +24070,7 @@ function createDurableAutoExtractor(options) {
|
|
|
23815
24070
|
return true;
|
|
23816
24071
|
},
|
|
23817
24072
|
isProcessing: () => running,
|
|
23818
|
-
dispose
|
|
23819
|
-
disposed = true;
|
|
23820
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
23821
|
-
}
|
|
24073
|
+
dispose
|
|
23822
24074
|
};
|
|
23823
24075
|
}
|
|
23824
24076
|
|
|
@@ -27090,6 +27342,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
|
|
|
27090
27342
|
var NO_CONVERSATION_KEY = "__no_conversation__";
|
|
27091
27343
|
var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
|
|
27092
27344
|
var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
|
|
27345
|
+
var MEMORY_STORE_NOT_READY = "Memory store is not ready";
|
|
27093
27346
|
var conversationRedactors = /* @__PURE__ */ new Map();
|
|
27094
27347
|
var clientToolFilterCache = /* @__PURE__ */ new Map();
|
|
27095
27348
|
function getConversationRedactor(conversationId, nerDetector) {
|
|
@@ -27234,7 +27487,7 @@ function useChatStorage(options) {
|
|
|
27234
27487
|
[resolvedPiiRedaction]
|
|
27235
27488
|
);
|
|
27236
27489
|
const maskEmbeddingInput = isPiiRedactor(resolvedPiiRedaction) ? maskForEmbedding : void 0;
|
|
27237
|
-
const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
27490
|
+
const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
|
|
27238
27491
|
const messagesCollection = (0, import_react5.useMemo)(() => database.get("history"), [database]);
|
|
27239
27492
|
const conversationsCollection = (0, import_react5.useMemo)(
|
|
27240
27493
|
() => database.get("conversations"),
|
|
@@ -27483,6 +27736,7 @@ function useChatStorage(options) {
|
|
|
27483
27736
|
}, [vaultEmbeddingCache]);
|
|
27484
27737
|
const retainVaultMemory = (0, import_react5.useCallback)(
|
|
27485
27738
|
async (input) => {
|
|
27739
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27486
27740
|
if (memoryStore) {
|
|
27487
27741
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
27488
27742
|
if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -27528,6 +27782,7 @@ function useChatStorage(options) {
|
|
|
27528
27782
|
);
|
|
27529
27783
|
const createMemoryVaultTool2 = (0, import_react5.useCallback)(
|
|
27530
27784
|
(options2) => {
|
|
27785
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27531
27786
|
if (storeMaskMissing) throw new Error(NO_STORE_MASK);
|
|
27532
27787
|
return createMemoryVaultTool(
|
|
27533
27788
|
memoryStore ?? vaultCtx,
|
|
@@ -27538,6 +27793,7 @@ function useChatStorage(options) {
|
|
|
27538
27793
|
);
|
|
27539
27794
|
const createRecallTool2 = (0, import_react5.useCallback)(
|
|
27540
27795
|
(toolOptions, callbacks) => {
|
|
27796
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27541
27797
|
if (!getToken && !memoryStore) {
|
|
27542
27798
|
throw new Error("getToken is required for recall tool");
|
|
27543
27799
|
}
|
|
@@ -27583,7 +27839,7 @@ function useChatStorage(options) {
|
|
|
27583
27839
|
);
|
|
27584
27840
|
const recallFn = (0, import_react5.useCallback)(
|
|
27585
27841
|
async (query, options2) => {
|
|
27586
|
-
if (!getToken && !memoryStore) {
|
|
27842
|
+
if (memoryStore === null || !getToken && !memoryStore) {
|
|
27587
27843
|
return {
|
|
27588
27844
|
memories: [],
|
|
27589
27845
|
usedBudget: options2?.budget ?? "low",
|
|
@@ -27632,6 +27888,7 @@ function useChatStorage(options) {
|
|
|
27632
27888
|
);
|
|
27633
27889
|
const getVaultMemories = (0, import_react5.useCallback)(
|
|
27634
27890
|
(options2) => {
|
|
27891
|
+
if (memoryStore === null) return Promise.resolve([]);
|
|
27635
27892
|
if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
|
|
27636
27893
|
const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
|
|
27637
27894
|
if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
|
|
@@ -27642,7 +27899,8 @@ function useChatStorage(options) {
|
|
|
27642
27899
|
[vaultCtx, memoryStore]
|
|
27643
27900
|
);
|
|
27644
27901
|
const deleteVaultMemory = (0, import_react5.useCallback)(
|
|
27645
|
-
(id) => {
|
|
27902
|
+
async (id) => {
|
|
27903
|
+
if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
|
|
27646
27904
|
return memoryStore ? memoryStore.delete(id) : deleteVaultMemoryOp(vaultCtx, id);
|
|
27647
27905
|
},
|
|
27648
27906
|
[vaultCtx, memoryStore]
|