@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/server/index.mjs
CHANGED
|
@@ -14928,6 +14928,10 @@ var require_stepsForMigration = __commonJS({
|
|
|
14928
14928
|
}
|
|
14929
14929
|
});
|
|
14930
14930
|
|
|
14931
|
+
// src/lib/chat/toolResultMessage.ts
|
|
14932
|
+
var FOOTER = "\n\nBased on these results, continue with the task.";
|
|
14933
|
+
var TOOL_RESULT_FOOTER_LINE = FOOTER.trim();
|
|
14934
|
+
|
|
14931
14935
|
// src/lib/tools/toolCatalog.ts
|
|
14932
14936
|
var TOOL_CATALOG = {
|
|
14933
14937
|
gmail_search_messages: { label: "Search emails", provider: "gmail", connector: "Gmail" },
|
|
@@ -15104,7 +15108,32 @@ ${neutralised}
|
|
|
15104
15108
|
}
|
|
15105
15109
|
|
|
15106
15110
|
// src/lib/chat/toolResults.ts
|
|
15111
|
+
var TOOL_RESULTS_PREFIX = "[Tool Execution Results]";
|
|
15112
|
+
var TOOL_LINE = /^Tool "([^"]+)" returned: (.*)$/;
|
|
15107
15113
|
var TOOL_RESULT_ORIGIN = "tool_result";
|
|
15114
|
+
function isToolResultsRow(row) {
|
|
15115
|
+
if (row.origin === TOOL_RESULT_ORIGIN) return true;
|
|
15116
|
+
if (typeof row.origin === "string") return false;
|
|
15117
|
+
if (row.role !== "user" || !row.content.startsWith(TOOL_RESULTS_PREFIX)) return false;
|
|
15118
|
+
return parseToolResultSegments(row.content).length > 0;
|
|
15119
|
+
}
|
|
15120
|
+
function parseToolResultSegments(content) {
|
|
15121
|
+
const segments = [];
|
|
15122
|
+
for (const raw of content.split("\n")) {
|
|
15123
|
+
const line = raw.trim();
|
|
15124
|
+
const match = TOOL_LINE.exec(line);
|
|
15125
|
+
if (match) {
|
|
15126
|
+
segments.push({ name: match[1], line });
|
|
15127
|
+
continue;
|
|
15128
|
+
}
|
|
15129
|
+
const current = segments[segments.length - 1];
|
|
15130
|
+
if (!current || line === "" || line === TOOL_RESULT_FOOTER_LINE) continue;
|
|
15131
|
+
if (line === TOOL_RESULTS_PREFIX) continue;
|
|
15132
|
+
current.line = `${current.line}
|
|
15133
|
+
${line}`;
|
|
15134
|
+
}
|
|
15135
|
+
return segments;
|
|
15136
|
+
}
|
|
15108
15137
|
|
|
15109
15138
|
// src/lib/db/chat/operations.ts
|
|
15110
15139
|
var import_watermelondb2 = __toESM(require_watermelondb());
|
|
@@ -16720,8 +16749,9 @@ async function getConversationsByProjectOp(ctx, projectId) {
|
|
|
16720
16749
|
)
|
|
16721
16750
|
);
|
|
16722
16751
|
}
|
|
16723
|
-
async function getMessagesOp(ctx, convId) {
|
|
16724
|
-
const
|
|
16752
|
+
async function getMessagesOp(ctx, convId, opts) {
|
|
16753
|
+
const fetched = await ctx.messagesCollection.query(import_watermelondb2.Q.where("conversation_id", convId), import_watermelondb2.Q.sortBy("message_id", import_watermelondb2.Q.asc)).unsafeFetchRaw();
|
|
16754
|
+
const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
|
|
16725
16755
|
return Promise.all(
|
|
16726
16756
|
results.map(
|
|
16727
16757
|
(raw) => messageRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
@@ -18448,6 +18478,22 @@ var postApiV1Embeddings = (options) => (options.client ?? client).post({
|
|
|
18448
18478
|
}
|
|
18449
18479
|
});
|
|
18450
18480
|
|
|
18481
|
+
// src/lib/memoryEngine/embeddingCacheState.ts
|
|
18482
|
+
var EMBEDDING_CACHE_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/embedding-cache/v1");
|
|
18483
|
+
var cacheGlobal = globalThis;
|
|
18484
|
+
var fallbackState = {
|
|
18485
|
+
scopedViews: /* @__PURE__ */ new WeakMap(),
|
|
18486
|
+
inFlightByCache: /* @__PURE__ */ new WeakMap(),
|
|
18487
|
+
cachedEmbeddingModels: /* @__PURE__ */ new WeakMap()
|
|
18488
|
+
};
|
|
18489
|
+
function getEmbeddingCacheState() {
|
|
18490
|
+
try {
|
|
18491
|
+
return cacheGlobal[EMBEDDING_CACHE_STATE_KEY] ?? (cacheGlobal[EMBEDDING_CACHE_STATE_KEY] = fallbackState);
|
|
18492
|
+
} catch {
|
|
18493
|
+
return fallbackState;
|
|
18494
|
+
}
|
|
18495
|
+
}
|
|
18496
|
+
|
|
18451
18497
|
// src/lib/memoryEngine/generate.ts
|
|
18452
18498
|
var EMBED_MAX_ATTEMPTS = 4;
|
|
18453
18499
|
var DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS = 15e3;
|
|
@@ -18539,15 +18585,18 @@ async function generateEmbedding(text12, options) {
|
|
|
18539
18585
|
if (total === void 0) return embedOne(text12, options, void 0);
|
|
18540
18586
|
return withDeadline((signal) => embedOne(text12, options, signal), total, "embedding");
|
|
18541
18587
|
}
|
|
18542
|
-
var inFlightByCache
|
|
18588
|
+
var { inFlightByCache, cachedEmbeddingModels } = getEmbeddingCacheState();
|
|
18543
18589
|
async function embedOne(text12, options, outer) {
|
|
18544
18590
|
const { cache } = options;
|
|
18545
18591
|
if (!cache) return Array.from(await requestEmbedding(text12, options, outer));
|
|
18592
|
+
const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18546
18593
|
const cached = cache.get(text12);
|
|
18547
|
-
|
|
18594
|
+
const cachedModel = cached && cachedEmbeddingModels.get(cached);
|
|
18595
|
+
if (cached && (cachedModel === void 0 || cachedModel === model)) return Array.from(cached);
|
|
18548
18596
|
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
18549
18597
|
inFlightByCache.set(cache, inFlight);
|
|
18550
|
-
const
|
|
18598
|
+
const requestKey = JSON.stringify([model, text12]);
|
|
18599
|
+
const pending = inFlight.get(requestKey);
|
|
18551
18600
|
if (pending) {
|
|
18552
18601
|
try {
|
|
18553
18602
|
return Array.from(await pending);
|
|
@@ -18556,13 +18605,14 @@ async function embedOne(text12, options, outer) {
|
|
|
18556
18605
|
}
|
|
18557
18606
|
}
|
|
18558
18607
|
const request = requestEmbedding(text12, options, outer);
|
|
18559
|
-
inFlight.set(
|
|
18608
|
+
inFlight.set(requestKey, request);
|
|
18560
18609
|
try {
|
|
18561
18610
|
const embedding = await request;
|
|
18611
|
+
cachedEmbeddingModels.set(embedding, model);
|
|
18562
18612
|
cache.set(text12, embedding);
|
|
18563
18613
|
return Array.from(embedding);
|
|
18564
18614
|
} finally {
|
|
18565
|
-
if (inFlight.get(
|
|
18615
|
+
if (inFlight.get(requestKey) === request) inFlight.delete(requestKey);
|
|
18566
18616
|
}
|
|
18567
18617
|
}
|
|
18568
18618
|
async function requestEmbedding(text12, options, outer) {
|
|
@@ -18645,13 +18695,15 @@ async function embedMany(texts, options, outer) {
|
|
|
18645
18695
|
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
18646
18696
|
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
18647
18697
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
18698
|
+
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18648
18699
|
const results = new Array(texts.length).fill(null);
|
|
18649
18700
|
const uncachedIndices = [];
|
|
18650
18701
|
const uncachedTexts = [];
|
|
18651
18702
|
for (let i = 0; i < texts.length; i++) {
|
|
18652
18703
|
if (cache) {
|
|
18653
18704
|
const cached = cache.get(texts[i]);
|
|
18654
|
-
|
|
18705
|
+
const cachedModel = cached && cachedEmbeddingModels.get(cached);
|
|
18706
|
+
if (cached && (cachedModel === void 0 || cachedModel === embeddingModel)) {
|
|
18655
18707
|
results[i] = Array.from(cached);
|
|
18656
18708
|
continue;
|
|
18657
18709
|
}
|
|
@@ -18667,7 +18719,6 @@ async function embedMany(texts, options, outer) {
|
|
|
18667
18719
|
...taskTypeHeader(options.taskType)
|
|
18668
18720
|
};
|
|
18669
18721
|
if (outer?.aborted) throw outer.reason;
|
|
18670
|
-
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18671
18722
|
let newEmbeddings;
|
|
18672
18723
|
if (uncachedTexts.length <= chunkSize) {
|
|
18673
18724
|
newEmbeddings = await generateEmbeddingsBatch(
|
|
@@ -18715,6 +18766,7 @@ async function embedMany(texts, options, outer) {
|
|
|
18715
18766
|
const f32Embedding = Float32Array.from(newEmbeddings[i]);
|
|
18716
18767
|
results[uncachedIndices[i]] = Array.from(f32Embedding);
|
|
18717
18768
|
if (cache) {
|
|
18769
|
+
cachedEmbeddingModels.set(f32Embedding, embeddingModel);
|
|
18718
18770
|
cache.set(uncachedTexts[i], f32Embedding);
|
|
18719
18771
|
}
|
|
18720
18772
|
}
|
|
@@ -18839,6 +18891,37 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
|
|
|
18839
18891
|
}));
|
|
18840
18892
|
return updateMessageChunksOp(ctx, messageId, messageChunks, embeddingModel);
|
|
18841
18893
|
}
|
|
18894
|
+
var MIN_SEALED_EMBEDDING_HEX = 256;
|
|
18895
|
+
function rawHasEmbedding(value) {
|
|
18896
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
18897
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
18898
|
+
if (isEncrypted(value)) {
|
|
18899
|
+
return value.length - value.indexOf(":", 4) - 1 >= MIN_SEALED_EMBEDDING_HEX;
|
|
18900
|
+
}
|
|
18901
|
+
try {
|
|
18902
|
+
const parsed = JSON.parse(value);
|
|
18903
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
18904
|
+
} catch {
|
|
18905
|
+
return false;
|
|
18906
|
+
}
|
|
18907
|
+
}
|
|
18908
|
+
function sealedVersion(value) {
|
|
18909
|
+
if (typeof value !== "string" || !isEncrypted(value)) return null;
|
|
18910
|
+
return value.startsWith("enc:v2:") ? "v2" : "v3";
|
|
18911
|
+
}
|
|
18912
|
+
function mayNeedChunkEmbedding(raw, embeddingModel, filter) {
|
|
18913
|
+
const role = raw.role;
|
|
18914
|
+
if (role === "system") return false;
|
|
18915
|
+
if (filter?.roles && !filter.roles.includes(role ?? "")) return false;
|
|
18916
|
+
if (isNonEmbeddableOrigin(raw.origin, filter?.reembedDiscarded)) {
|
|
18917
|
+
return false;
|
|
18918
|
+
}
|
|
18919
|
+
const model = raw.embedding_model;
|
|
18920
|
+
if (typeof model === "string" && model !== embeddingModel) return true;
|
|
18921
|
+
if (rawHasEmbedding(raw.chunks)) return false;
|
|
18922
|
+
if (rawHasEmbedding(raw.vector) && !filter?.rechunkExisting) return false;
|
|
18923
|
+
return true;
|
|
18924
|
+
}
|
|
18842
18925
|
async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
18843
18926
|
const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18844
18927
|
const { chunkSize = DEFAULT_CHUNK_SIZE } = options;
|
|
@@ -18851,11 +18934,31 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
18851
18934
|
let considered = 0;
|
|
18852
18935
|
let sealedRowsSeen = 0;
|
|
18853
18936
|
let rowsSeen = 0;
|
|
18937
|
+
const keptSealed = /* @__PURE__ */ new Map();
|
|
18938
|
+
const candidatesStillSealed = /* @__PURE__ */ new Map();
|
|
18939
|
+
const droppedSealed = /* @__PURE__ */ new Map();
|
|
18940
|
+
const rawFilter = (raw) => {
|
|
18941
|
+
rowsSeen++;
|
|
18942
|
+
const keep = mayNeedChunkEmbedding(raw, embeddingModel, filter);
|
|
18943
|
+
const version = sealedVersion(raw.content);
|
|
18944
|
+
if (!version) return keep;
|
|
18945
|
+
if (keep) {
|
|
18946
|
+
keptSealed.set(version, (keptSealed.get(version) ?? 0) + 1);
|
|
18947
|
+
} else {
|
|
18948
|
+
const dropped = droppedSealed.get(version);
|
|
18949
|
+
if (dropped) dropped.count++;
|
|
18950
|
+
else droppedSealed.set(version, { count: 1, probeId: raw.id });
|
|
18951
|
+
}
|
|
18952
|
+
return keep;
|
|
18953
|
+
};
|
|
18854
18954
|
for (const conv of targetConversations) {
|
|
18855
|
-
const messages = await getMessagesOp(ctx, conv.conversationId);
|
|
18955
|
+
const messages = await getMessagesOp(ctx, conv.conversationId, { rawFilter });
|
|
18856
18956
|
for (const message of messages) {
|
|
18857
|
-
|
|
18858
|
-
if (
|
|
18957
|
+
const stillSealed = sealedVersion(message.content);
|
|
18958
|
+
if (stillSealed) {
|
|
18959
|
+
sealedRowsSeen++;
|
|
18960
|
+
candidatesStillSealed.set(stillSealed, (candidatesStillSealed.get(stillSealed) ?? 0) + 1);
|
|
18961
|
+
}
|
|
18859
18962
|
const isStale = message.embeddingModel !== void 0 && message.embeddingModel !== null && message.embeddingModel !== embeddingModel;
|
|
18860
18963
|
if (message.chunks && message.chunks.length > 0 && !isStale) continue;
|
|
18861
18964
|
const hasVector = message.vector && message.vector.length > 0;
|
|
@@ -18868,6 +18971,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
18868
18971
|
stillEncrypted++;
|
|
18869
18972
|
continue;
|
|
18870
18973
|
}
|
|
18974
|
+
if (isToolResultsRow(message)) continue;
|
|
18871
18975
|
if (message.content.length < minLength) continue;
|
|
18872
18976
|
if (shouldChunkMessage(message.content, chunkSize)) {
|
|
18873
18977
|
longMessages.push({
|
|
@@ -18879,6 +18983,12 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
18879
18983
|
}
|
|
18880
18984
|
}
|
|
18881
18985
|
}
|
|
18986
|
+
for (const [version, dropped] of droppedSealed) {
|
|
18987
|
+
const keyOpenedACandidate = (keptSealed.get(version) ?? 0) > (candidatesStillSealed.get(version) ?? 0);
|
|
18988
|
+
if (keyOpenedACandidate) continue;
|
|
18989
|
+
const probe = await getMessageOp(ctx, dropped.probeId);
|
|
18990
|
+
if (!probe || isEncrypted(probe.content)) sealedRowsSeen += dropped.count;
|
|
18991
|
+
}
|
|
18882
18992
|
if (stillEncrypted > 0 || sealedRowsSeen > 0) {
|
|
18883
18993
|
getLogger().error(
|
|
18884
18994
|
"memoryEngine: messages still encrypted (key unavailable?) \u2014 excluded from embedding",
|
|
@@ -26030,6 +26140,11 @@ function parseTopics(value) {
|
|
|
26030
26140
|
}
|
|
26031
26141
|
|
|
26032
26142
|
// src/lib/db/entities/operations.ts
|
|
26143
|
+
async function assertCanWrite(ctx) {
|
|
26144
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
26145
|
+
throw new Error("Memory source is no longer eligible");
|
|
26146
|
+
}
|
|
26147
|
+
}
|
|
26033
26148
|
function entityToStored(e) {
|
|
26034
26149
|
return {
|
|
26035
26150
|
uniqueId: e.id,
|
|
@@ -26170,6 +26285,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
26170
26285
|
let skipped = false;
|
|
26171
26286
|
let entities = [];
|
|
26172
26287
|
await ctx.database.write(async () => {
|
|
26288
|
+
await assertCanWrite(ctx);
|
|
26173
26289
|
const {
|
|
26174
26290
|
entities: byName,
|
|
26175
26291
|
operations: entityOps,
|
|
@@ -26245,6 +26361,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
26245
26361
|
let skipped = false;
|
|
26246
26362
|
let entities = [];
|
|
26247
26363
|
await ctx.database.write(async () => {
|
|
26364
|
+
await assertCanWrite(ctx);
|
|
26248
26365
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
26249
26366
|
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
26250
26367
|
skipped = true;
|
|
@@ -26305,6 +26422,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
|
26305
26422
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb18.Q.where("memory_id", import_watermelondb18.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
26306
26423
|
if (links.length === 0) return;
|
|
26307
26424
|
await ctx.database.write(async () => {
|
|
26425
|
+
await assertCanWrite(ctx);
|
|
26308
26426
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
26309
26427
|
});
|
|
26310
26428
|
}
|
|
@@ -26313,6 +26431,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
|
|
|
26313
26431
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb18.Q.where("user_id", userId)).fetch();
|
|
26314
26432
|
if (links.length === 0) return;
|
|
26315
26433
|
await ctx.database.write(async () => {
|
|
26434
|
+
await assertCanWrite(ctx);
|
|
26316
26435
|
await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
|
|
26317
26436
|
});
|
|
26318
26437
|
}
|
|
@@ -26476,6 +26595,11 @@ function visibilityConditions(requested) {
|
|
|
26476
26595
|
function isKinded(record) {
|
|
26477
26596
|
return record.kind !== null && record.kind !== void 0;
|
|
26478
26597
|
}
|
|
26598
|
+
async function assertCanWrite2(ctx) {
|
|
26599
|
+
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
26600
|
+
throw new Error("Memory source is no longer eligible");
|
|
26601
|
+
}
|
|
26602
|
+
}
|
|
26479
26603
|
function assertValidKindLevel(kind, level) {
|
|
26480
26604
|
const hasKind = kind !== null && kind !== void 0;
|
|
26481
26605
|
if (hasKind && !MEMORY_KINDS.includes(kind)) {
|
|
@@ -26656,8 +26780,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
26656
26780
|
ctx.embeddedWalletSigner
|
|
26657
26781
|
) : opts.content;
|
|
26658
26782
|
const created = await ctx.database.write(async () => {
|
|
26659
|
-
|
|
26660
|
-
throw new Error("Memory source is no longer eligible");
|
|
26783
|
+
await assertCanWrite2(ctx);
|
|
26661
26784
|
return ctx.vaultMemoryCollection.create(
|
|
26662
26785
|
(record) => populateNewVaultMemory(record, ctx, opts, encryptedContent, encryptedKindValue)
|
|
26663
26786
|
);
|
|
@@ -26676,8 +26799,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
26676
26799
|
) : opts.content;
|
|
26677
26800
|
let createdRecord = null;
|
|
26678
26801
|
await ctx.database.write(async () => {
|
|
26679
|
-
|
|
26680
|
-
throw new Error("Memory source is no longer eligible");
|
|
26802
|
+
await assertCanWrite2(ctx);
|
|
26681
26803
|
let target;
|
|
26682
26804
|
try {
|
|
26683
26805
|
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
@@ -26769,8 +26891,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
26769
26891
|
})
|
|
26770
26892
|
);
|
|
26771
26893
|
const created = await ctx.database.write(async () => {
|
|
26772
|
-
|
|
26773
|
-
throw new Error("Memory source is no longer eligible");
|
|
26894
|
+
await assertCanWrite2(ctx);
|
|
26774
26895
|
const prepared = optionsArray.map(
|
|
26775
26896
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
26776
26897
|
(record) => populateNewVaultMemory(record, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
@@ -27061,8 +27182,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
27061
27182
|
const record = probe;
|
|
27062
27183
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
27063
27184
|
await ctx.database.write(async () => {
|
|
27064
|
-
|
|
27065
|
-
throw new Error("Memory source is no longer eligible");
|
|
27185
|
+
await assertCanWrite2(ctx);
|
|
27066
27186
|
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record) || opts.freeFormOnly && isKinded(record)) {
|
|
27067
27187
|
stale = true;
|
|
27068
27188
|
return;
|
|
@@ -27173,6 +27293,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
27173
27293
|
let stale = false;
|
|
27174
27294
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
27175
27295
|
await ctx.database.write(async (writer) => {
|
|
27296
|
+
await assertCanWrite2(ctx);
|
|
27176
27297
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
27177
27298
|
stale = true;
|
|
27178
27299
|
return;
|
|
@@ -27214,6 +27335,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
27214
27335
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
27215
27336
|
let cleared = false;
|
|
27216
27337
|
await ctx.database.write(async () => {
|
|
27338
|
+
await assertCanWrite2(ctx);
|
|
27217
27339
|
if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
|
|
27218
27340
|
cleared = true;
|
|
27219
27341
|
await record.update((r) => {
|
|
@@ -27237,6 +27359,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
|
27237
27359
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
|
|
27238
27360
|
let stale = false;
|
|
27239
27361
|
await ctx.database.write(async () => {
|
|
27362
|
+
await assertCanWrite2(ctx);
|
|
27240
27363
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
27241
27364
|
stale = true;
|
|
27242
27365
|
return;
|
|
@@ -27265,6 +27388,7 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
27265
27388
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
27266
27389
|
let stale = false;
|
|
27267
27390
|
await ctx.database.write(async () => {
|
|
27391
|
+
await assertCanWrite2(ctx);
|
|
27268
27392
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
27269
27393
|
stale = true;
|
|
27270
27394
|
return;
|
|
@@ -27302,8 +27426,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
|
27302
27426
|
}
|
|
27303
27427
|
let stale = false;
|
|
27304
27428
|
await ctx.database.write(async () => {
|
|
27305
|
-
|
|
27306
|
-
throw new Error("Memory source is no longer eligible");
|
|
27429
|
+
await assertCanWrite2(ctx);
|
|
27307
27430
|
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
27308
27431
|
stale = true;
|
|
27309
27432
|
return;
|
|
@@ -27465,6 +27588,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
27465
27588
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
27466
27589
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
27467
27590
|
await ctx.database.write(async () => {
|
|
27591
|
+
await assertCanWrite2(ctx);
|
|
27468
27592
|
const records = [];
|
|
27469
27593
|
for (const id of chunkIds) {
|
|
27470
27594
|
try {
|
|
@@ -27498,6 +27622,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
27498
27622
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
27499
27623
|
try {
|
|
27500
27624
|
await ctx.database.write(async (writer) => {
|
|
27625
|
+
await assertCanWrite2(ctx);
|
|
27501
27626
|
let record;
|
|
27502
27627
|
try {
|
|
27503
27628
|
record = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -27528,6 +27653,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
27528
27653
|
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
27529
27654
|
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
27530
27655
|
await ctx.database.write(async () => {
|
|
27656
|
+
await assertCanWrite2(ctx);
|
|
27531
27657
|
const writes = [];
|
|
27532
27658
|
for (const id of chunkIds) {
|
|
27533
27659
|
let record;
|
|
@@ -27560,6 +27686,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
27560
27686
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb19.Q.where("user_id", userId), import_watermelondb19.Q.where("is_deleted", false)).fetch();
|
|
27561
27687
|
if (records.length === 0) return 0;
|
|
27562
27688
|
await ctx.database.write(async () => {
|
|
27689
|
+
await assertCanWrite2(ctx);
|
|
27563
27690
|
const prepared = records.map(
|
|
27564
27691
|
(record) => record.prepareUpdate((r) => {
|
|
27565
27692
|
r._setRaw("is_deleted", true);
|
|
@@ -27614,6 +27741,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
|
27614
27741
|
let stale = false;
|
|
27615
27742
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
27616
27743
|
await ctx.database.write(async () => {
|
|
27744
|
+
await assertCanWrite2(ctx);
|
|
27617
27745
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
|
|
27618
27746
|
stale = true;
|
|
27619
27747
|
return;
|
|
@@ -27637,6 +27765,7 @@ async function restoreVaultMemoryOp(ctx, id) {
|
|
|
27637
27765
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
27638
27766
|
let stale = false;
|
|
27639
27767
|
await ctx.database.write(async () => {
|
|
27768
|
+
await assertCanWrite2(ctx);
|
|
27640
27769
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
27641
27770
|
stale = true;
|
|
27642
27771
|
return;
|
|
@@ -27657,6 +27786,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
|
27657
27786
|
const now = opts.now ?? Date.now();
|
|
27658
27787
|
let stale = false;
|
|
27659
27788
|
await ctx.database.write(async () => {
|
|
27789
|
+
await assertCanWrite2(ctx);
|
|
27660
27790
|
const archivedAt = record.archivedAt;
|
|
27661
27791
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
27662
27792
|
stale = true;
|
|
@@ -27696,6 +27826,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
|
|
|
27696
27826
|
}
|
|
27697
27827
|
let written = false;
|
|
27698
27828
|
await ctx.database.write(async () => {
|
|
27829
|
+
await assertCanWrite2(ctx);
|
|
27699
27830
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
|
|
27700
27831
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
27701
27832
|
if (originalUpdatedAt !== readUpdatedAt || record._getRaw("content") !== readStoredContent)
|
|
@@ -31367,6 +31498,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
31367
31498
|
).map((c) => c.candidate);
|
|
31368
31499
|
}
|
|
31369
31500
|
async function extractAndRetain(messages, retainCtx, options) {
|
|
31501
|
+
const { memoryStore, signal } = options;
|
|
31502
|
+
if (memoryStore === null) throw new Error("Memory store is not ready");
|
|
31503
|
+
if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
|
|
31504
|
+
throw new Error("Remote memory extraction does not support folders");
|
|
31505
|
+
if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
|
|
31506
|
+
throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
|
|
31507
|
+
signal?.throwIfAborted();
|
|
31370
31508
|
const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
31371
31509
|
const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
|
|
31372
31510
|
const consolidateOptions = options.consolidateOptions !== void 0 ? {
|
|
@@ -31400,6 +31538,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
31400
31538
|
}
|
|
31401
31539
|
});
|
|
31402
31540
|
const extractMs = Date.now() - tExtract;
|
|
31541
|
+
signal?.throwIfAborted();
|
|
31403
31542
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
31404
31543
|
const log = getLogger();
|
|
31405
31544
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -31447,16 +31586,33 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
31447
31586
|
const results = [];
|
|
31448
31587
|
const quarantinedInfo = [];
|
|
31449
31588
|
let failedWrites = 0;
|
|
31589
|
+
let auditRows;
|
|
31450
31590
|
const tRetain = Date.now();
|
|
31451
31591
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
31452
31592
|
try {
|
|
31593
|
+
signal?.throwIfAborted();
|
|
31453
31594
|
if (isQuarantined) {
|
|
31454
|
-
|
|
31455
|
-
|
|
31456
|
-
|
|
31457
|
-
|
|
31458
|
-
|
|
31459
|
-
|
|
31595
|
+
let existingId;
|
|
31596
|
+
if (memoryStore) {
|
|
31597
|
+
auditRows ?? (auditRows = memoryStore.list({
|
|
31598
|
+
scopes: [options.scope ?? "private"],
|
|
31599
|
+
includeArchived: true,
|
|
31600
|
+
includeQuarantined: true,
|
|
31601
|
+
includeSuperseded: true
|
|
31602
|
+
}));
|
|
31603
|
+
const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
|
|
31604
|
+
const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
31605
|
+
existingId = (await auditRows).find(
|
|
31606
|
+
(row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
|
|
31607
|
+
)?.uniqueId ?? null;
|
|
31608
|
+
} else {
|
|
31609
|
+
existingId = await findQuarantinedDuplicateOp(
|
|
31610
|
+
retainCtx.vaultCtx,
|
|
31611
|
+
candidate.content,
|
|
31612
|
+
candidate.sourceMessageIds,
|
|
31613
|
+
{ scope: options.scope ?? "private", folderId: options.folderId ?? null }
|
|
31614
|
+
).catch(() => null);
|
|
31615
|
+
}
|
|
31460
31616
|
if (existingId) {
|
|
31461
31617
|
quarantinedInfo.push({
|
|
31462
31618
|
candidate,
|
|
@@ -31467,18 +31623,26 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
31467
31623
|
continue;
|
|
31468
31624
|
}
|
|
31469
31625
|
}
|
|
31470
|
-
const
|
|
31626
|
+
const retainOptions = {
|
|
31471
31627
|
source: "auto-extracted",
|
|
31472
31628
|
sourceChunkIds: candidate.sourceMessageIds,
|
|
31473
31629
|
respectTombstones: true,
|
|
31474
31630
|
...options.scope !== void 0 && { scope: options.scope },
|
|
31475
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
31476
31631
|
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
31477
31632
|
...candidate.eventTime !== null && { eventTime: candidate.eventTime },
|
|
31478
31633
|
factType: candidate.type,
|
|
31479
31634
|
...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
|
|
31635
|
+
};
|
|
31636
|
+
const result = memoryStore ? await memoryStore.retain(candidate.content, {
|
|
31637
|
+
...retainOptions,
|
|
31638
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
31639
|
+
signal
|
|
31640
|
+
}) : await retain(candidate.content, retainCtx, {
|
|
31641
|
+
...retainOptions,
|
|
31642
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
31480
31643
|
});
|
|
31481
31644
|
if (isQuarantined) {
|
|
31645
|
+
auditRows = void 0;
|
|
31482
31646
|
const info = {
|
|
31483
31647
|
candidate,
|
|
31484
31648
|
memoryId: result.memoryId,
|
|
@@ -31497,9 +31661,16 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
31497
31661
|
}
|
|
31498
31662
|
succeededCandidates.push(candidate);
|
|
31499
31663
|
results.push(result);
|
|
31500
|
-
if (result.action !== "suppressed" &&
|
|
31664
|
+
if (result.action !== "suppressed" && candidate.entities.length > 0) {
|
|
31501
31665
|
try {
|
|
31502
|
-
|
|
31666
|
+
signal?.throwIfAborted();
|
|
31667
|
+
if (memoryStore) {
|
|
31668
|
+
await memoryStore.addTopics(result.memoryId, candidate.entities, {
|
|
31669
|
+
unlessUserManaged: true,
|
|
31670
|
+
canWrite: retainCtx.vaultCtx.canWrite,
|
|
31671
|
+
signal
|
|
31672
|
+
});
|
|
31673
|
+
} else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
|
|
31503
31674
|
await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
|
|
31504
31675
|
unlessTopicsUserManaged: true
|
|
31505
31676
|
});
|
|
@@ -31747,7 +31918,7 @@ function createAutoExtractor(options) {
|
|
|
31747
31918
|
};
|
|
31748
31919
|
const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
|
|
31749
31920
|
const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
|
|
31750
|
-
if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
31921
|
+
if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
|
|
31751
31922
|
getLogger().warn(
|
|
31752
31923
|
"[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
|
|
31753
31924
|
);
|
|
@@ -31792,6 +31963,8 @@ function createAutoExtractor(options) {
|
|
|
31792
31963
|
try {
|
|
31793
31964
|
const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
31794
31965
|
extract,
|
|
31966
|
+
memoryStore: options.memoryStore,
|
|
31967
|
+
signal: options.signal,
|
|
31795
31968
|
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
31796
31969
|
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
31797
31970
|
...options.scope !== void 0 && { scope: options.scope },
|
|
@@ -32444,7 +32617,7 @@ var MaskScopedEmbeddingCache = class extends Map {
|
|
|
32444
32617
|
return this;
|
|
32445
32618
|
}
|
|
32446
32619
|
};
|
|
32447
|
-
var scopedViews =
|
|
32620
|
+
var { scopedViews } = getEmbeddingCacheState();
|
|
32448
32621
|
function maskScopedEmbeddingCache(cache, masked) {
|
|
32449
32622
|
const views = scopedViews.get(cache) ?? {};
|
|
32450
32623
|
scopedViews.set(cache, views);
|
|
@@ -32866,44 +33039,48 @@ async function recall(query, ctx, options = {}) {
|
|
|
32866
33039
|
embeddingOptions,
|
|
32867
33040
|
ctx.vaultCache,
|
|
32868
33041
|
searchOptions
|
|
32869
|
-
)))(
|
|
32870
|
-
|
|
32871
|
-
|
|
32872
|
-
|
|
32873
|
-
|
|
32874
|
-
|
|
32875
|
-
|
|
32876
|
-
|
|
32877
|
-
|
|
32878
|
-
|
|
32879
|
-
|
|
32880
|
-
|
|
32881
|
-
|
|
32882
|
-
|
|
32883
|
-
|
|
32884
|
-
|
|
32885
|
-
|
|
32886
|
-
|
|
32887
|
-
|
|
32888
|
-
|
|
32889
|
-
|
|
32890
|
-
|
|
32891
|
-
|
|
32892
|
-
|
|
33042
|
+
)))(
|
|
33043
|
+
query,
|
|
33044
|
+
{
|
|
33045
|
+
limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
|
|
33046
|
+
minSimilarity: vaultMinScore,
|
|
33047
|
+
useFusion: true,
|
|
33048
|
+
rerank: flags.rerank,
|
|
33049
|
+
...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
|
|
33050
|
+
...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
|
|
33051
|
+
...options.rerankLoadTimeoutMs !== void 0 && {
|
|
33052
|
+
rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
|
|
33053
|
+
},
|
|
33054
|
+
...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
|
|
33055
|
+
...options.recency && { recency: options.recency },
|
|
33056
|
+
...options.mmr !== void 0 && { mmr: options.mmr },
|
|
33057
|
+
...options.supersessionBoost !== void 0 && {
|
|
33058
|
+
supersessionBoost: options.supersessionBoost
|
|
33059
|
+
},
|
|
33060
|
+
...options.supersessionWindow !== void 0 && {
|
|
33061
|
+
supersessionWindow: options.supersessionWindow
|
|
33062
|
+
},
|
|
33063
|
+
...options.proofCountAlpha !== void 0 && {
|
|
33064
|
+
proofCountAlpha: options.proofCountAlpha
|
|
33065
|
+
},
|
|
33066
|
+
...options.bm25AdmissionDivisor !== void 0 && {
|
|
33067
|
+
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
33068
|
+
},
|
|
33069
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
33070
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
33071
|
+
...subQueries && { subQueries },
|
|
33072
|
+
...options.scopes && { scopes: options.scopes },
|
|
33073
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
33074
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
33075
|
+
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
33076
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
33077
|
+
...entityRanking.length > 0 && { entityRanking },
|
|
33078
|
+
...temporalRanking.length > 0 && { temporalRanking },
|
|
33079
|
+
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
33080
|
+
queryEmbedTotalTimeoutMs
|
|
32893
33081
|
},
|
|
32894
|
-
|
|
32895
|
-
|
|
32896
|
-
...subQueries && { subQueries },
|
|
32897
|
-
...options.scopes && { scopes: options.scopes },
|
|
32898
|
-
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
32899
|
-
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
32900
|
-
...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
|
|
32901
|
-
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
32902
|
-
...entityRanking.length > 0 && { entityRanking },
|
|
32903
|
-
...temporalRanking.length > 0 && { temporalRanking },
|
|
32904
|
-
...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
|
|
32905
|
-
queryEmbedTotalTimeoutMs
|
|
32906
|
-
});
|
|
33082
|
+
options.embeddingCache
|
|
33083
|
+
);
|
|
32907
33084
|
factResults.push(
|
|
32908
33085
|
...dedupeBy(
|
|
32909
33086
|
results,
|
|
@@ -33900,6 +34077,7 @@ function createLocalMemoryStore(options) {
|
|
|
33900
34077
|
database,
|
|
33901
34078
|
entityCollection: database.get("entity"),
|
|
33902
34079
|
memoryEntityCollection: database.get("memory_entity"),
|
|
34080
|
+
canWrite: options.canWrite,
|
|
33903
34081
|
...userId !== void 0 && { userId },
|
|
33904
34082
|
...options.allowUnscopedRows !== void 0 && {
|
|
33905
34083
|
allowUnscopedRows: options.allowUnscopedRows
|
|
@@ -33911,10 +34089,21 @@ function createLocalMemoryStore(options) {
|
|
|
33911
34089
|
walletAddress: options.walletAddress,
|
|
33912
34090
|
signMessage: options.signMessage,
|
|
33913
34091
|
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
34092
|
+
canWrite: options.canWrite,
|
|
33914
34093
|
...userId !== void 0 && { userId },
|
|
33915
34094
|
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
33916
34095
|
entityCtx
|
|
33917
34096
|
};
|
|
34097
|
+
const assertWrite = async (writeOptions) => {
|
|
34098
|
+
writeOptions?.signal?.throwIfAborted();
|
|
34099
|
+
if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
|
|
34100
|
+
throw new Error("Memory source is no longer eligible");
|
|
34101
|
+
}
|
|
34102
|
+
if (options.canWrite && !await options.canWrite()) {
|
|
34103
|
+
throw new Error("Memory source is no longer eligible");
|
|
34104
|
+
}
|
|
34105
|
+
writeOptions?.signal?.throwIfAborted();
|
|
34106
|
+
};
|
|
33918
34107
|
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
33919
34108
|
const ownedBy = userId !== void 0 ? [import_watermelondb24.Q.where("user_id", userId)] : [];
|
|
33920
34109
|
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb24.Q.or(import_watermelondb24.Q.where("user_id", userId), import_watermelondb24.Q.where("user_id", null))] : [import_watermelondb24.Q.where("user_id", userId)];
|
|
@@ -34026,9 +34215,25 @@ function createLocalMemoryStore(options) {
|
|
|
34026
34215
|
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
34027
34216
|
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
34028
34217
|
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
34029
|
-
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
34218
|
+
addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
|
|
34219
|
+
await assertWrite(writeOptions);
|
|
34030
34220
|
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb24.Q.where("id", memoryId), import_watermelondb24.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
34031
|
-
return owned > 0 ? writer.callWriter(
|
|
34221
|
+
return owned > 0 ? writer.callWriter(
|
|
34222
|
+
() => linkMemoryEntitiesOp(
|
|
34223
|
+
{
|
|
34224
|
+
...entityCtx,
|
|
34225
|
+
canWrite: async () => {
|
|
34226
|
+
await assertWrite(writeOptions);
|
|
34227
|
+
return true;
|
|
34228
|
+
}
|
|
34229
|
+
},
|
|
34230
|
+
memoryId,
|
|
34231
|
+
topics,
|
|
34232
|
+
{
|
|
34233
|
+
unlessTopicsUserManaged: writeOptions?.unlessUserManaged
|
|
34234
|
+
}
|
|
34235
|
+
)
|
|
34236
|
+
) : [];
|
|
34032
34237
|
}),
|
|
34033
34238
|
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
34034
34239
|
recall: (query, recallOptions) => recall(
|
|
@@ -34038,14 +34243,33 @@ function createLocalMemoryStore(options) {
|
|
|
34038
34243
|
),
|
|
34039
34244
|
retain: (content, retainOptions) => retain(
|
|
34040
34245
|
content,
|
|
34041
|
-
{
|
|
34246
|
+
{
|
|
34247
|
+
vaultCtx: {
|
|
34248
|
+
...vaultCtx,
|
|
34249
|
+
canWrite: async () => {
|
|
34250
|
+
await assertWrite(retainOptions);
|
|
34251
|
+
return true;
|
|
34252
|
+
}
|
|
34253
|
+
},
|
|
34254
|
+
embeddingOptions: options.embeddingOptions,
|
|
34255
|
+
vaultCache
|
|
34256
|
+
},
|
|
34042
34257
|
retainOptions
|
|
34043
34258
|
),
|
|
34044
34259
|
factSource: {
|
|
34045
|
-
search: (query, searchOptions) => searchVaultMemoriesWithSize(
|
|
34260
|
+
search: (query, searchOptions, embeddingCache) => searchVaultMemoriesWithSize(
|
|
34046
34261
|
query,
|
|
34047
34262
|
vaultCtx,
|
|
34048
|
-
{
|
|
34263
|
+
{
|
|
34264
|
+
...options.embeddingOptions,
|
|
34265
|
+
taskType: "memory_recall_embed",
|
|
34266
|
+
...embeddingCache && !options.embeddingOptions.cache && {
|
|
34267
|
+
cache: maskScopedEmbeddingCache(
|
|
34268
|
+
embeddingCache,
|
|
34269
|
+
Boolean(options.embeddingOptions.maskInput)
|
|
34270
|
+
)
|
|
34271
|
+
}
|
|
34272
|
+
},
|
|
34049
34273
|
vaultCache,
|
|
34050
34274
|
searchOptions
|
|
34051
34275
|
),
|
|
@@ -34879,6 +35103,7 @@ function createDurableAutoExtractor(options) {
|
|
|
34879
35103
|
};
|
|
34880
35104
|
const folderId = options.folderId ?? null;
|
|
34881
35105
|
let disposed = false;
|
|
35106
|
+
let activeBatch = null;
|
|
34882
35107
|
let running = false;
|
|
34883
35108
|
let wakeRequested = false;
|
|
34884
35109
|
let timer;
|
|
@@ -34915,14 +35140,18 @@ function createDurableAutoExtractor(options) {
|
|
|
34915
35140
|
}, delay);
|
|
34916
35141
|
}
|
|
34917
35142
|
async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
|
|
35143
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
34918
35144
|
let watchdog;
|
|
34919
35145
|
let cancelled = false;
|
|
35146
|
+
const controller = new AbortController();
|
|
35147
|
+
activeBatch = controller;
|
|
34920
35148
|
const model = options.modelForScope?.(jobScope) ?? options.extract.model;
|
|
34921
35149
|
try {
|
|
34922
35150
|
return await Promise.race([
|
|
34923
35151
|
new Promise((resolve, reject) => {
|
|
34924
35152
|
const worker = createAutoExtractor({
|
|
34925
35153
|
...options,
|
|
35154
|
+
signal: controller.signal,
|
|
34926
35155
|
retainCtx: {
|
|
34927
35156
|
...options.retainCtx,
|
|
34928
35157
|
vaultCtx: {
|
|
@@ -34951,6 +35180,8 @@ function createDurableAutoExtractor(options) {
|
|
|
34951
35180
|
]);
|
|
34952
35181
|
} finally {
|
|
34953
35182
|
cancelled = true;
|
|
35183
|
+
controller.abort();
|
|
35184
|
+
if (activeBatch === controller) activeBatch = null;
|
|
34954
35185
|
if (watchdog !== void 0) clearTimeout(watchdog);
|
|
34955
35186
|
}
|
|
34956
35187
|
}
|
|
@@ -34962,6 +35193,7 @@ function createDurableAutoExtractor(options) {
|
|
|
34962
35193
|
for (const message of loaded)
|
|
34963
35194
|
if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
|
|
34964
35195
|
await database.write(async () => {
|
|
35196
|
+
if (disposed) return;
|
|
34965
35197
|
const current = idsOf(job);
|
|
34966
35198
|
const acknowledged = ids.filter((id) => current.includes(id));
|
|
34967
35199
|
if (!acknowledged.length) return;
|
|
@@ -35134,6 +35366,7 @@ function createDurableAutoExtractor(options) {
|
|
|
35134
35366
|
jobScope,
|
|
35135
35367
|
jobFolderId
|
|
35136
35368
|
);
|
|
35369
|
+
if (disposed) throw new Error("Extraction session was disposed");
|
|
35137
35370
|
options.onTurnComplete?.(result);
|
|
35138
35371
|
return result;
|
|
35139
35372
|
};
|
|
@@ -35170,6 +35403,7 @@ function createDurableAutoExtractor(options) {
|
|
|
35170
35403
|
);
|
|
35171
35404
|
scheduleAfterSuccess = true;
|
|
35172
35405
|
} catch (error) {
|
|
35406
|
+
if (disposed) break;
|
|
35173
35407
|
attempts.set(job.id, attempted + 1);
|
|
35174
35408
|
retry = true;
|
|
35175
35409
|
reportError(error, conversationId);
|
|
@@ -35192,6 +35426,14 @@ function createDurableAutoExtractor(options) {
|
|
|
35192
35426
|
schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
|
|
35193
35427
|
}
|
|
35194
35428
|
}
|
|
35429
|
+
function dispose() {
|
|
35430
|
+
disposed = true;
|
|
35431
|
+
activeBatch?.abort(options.signal?.reason);
|
|
35432
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
35433
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
35434
|
+
}
|
|
35435
|
+
if (options.signal?.aborted) dispose();
|
|
35436
|
+
else options.signal?.addEventListener("abort", dispose, { once: true });
|
|
35195
35437
|
schedule(0);
|
|
35196
35438
|
return {
|
|
35197
35439
|
processTurn(messages, conversationId) {
|
|
@@ -35271,10 +35513,7 @@ function createDurableAutoExtractor(options) {
|
|
|
35271
35513
|
return true;
|
|
35272
35514
|
},
|
|
35273
35515
|
isProcessing: () => running,
|
|
35274
|
-
dispose
|
|
35275
|
-
disposed = true;
|
|
35276
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
35277
|
-
}
|
|
35516
|
+
dispose
|
|
35278
35517
|
};
|
|
35279
35518
|
}
|
|
35280
35519
|
|