@anuma/sdk 3.8.4 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/{chunk-42Y42CAZ.mjs → chunk-YFJAHJMB.mjs} +278 -62
- package/dist/expo/index.cjs +283 -64
- package/dist/expo/index.d.mts +25 -0
- package/dist/expo/index.d.ts +25 -0
- package/dist/expo/index.mjs +6 -4
- package/dist/expo/{recall-JFZ3Z6EX.mjs → recall-KWTVD4IR.mjs} +1 -1
- package/dist/react/{chunk-NLVSQAYH.mjs → chunk-GDS7GHBF.mjs} +305 -62
- package/dist/react/index.cjs +314 -64
- package/dist/react/index.d.mts +114 -1
- package/dist/react/index.d.ts +114 -1
- package/dist/react/index.mjs +14 -4
- package/dist/react/{recall-BCEH7U2Z.mjs → recall-SBQ4LNRJ.mjs} +1 -1
- package/dist/server/{chunk-FS56IDOW.mjs → chunk-QC4WHNIJ.mjs} +278 -62
- package/dist/server/index.cjs +283 -64
- package/dist/server/index.d.mts +25 -0
- package/dist/server/index.d.ts +25 -0
- package/dist/server/index.mjs +6 -4
- package/dist/server/{recall-VDMDNQNB.mjs → recall-NLJNELJY.mjs} +1 -1
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -17389,6 +17389,85 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
17389
17389
|
(raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
17390
17390
|
);
|
|
17391
17391
|
}
|
|
17392
|
+
function baseVaultSql(ctx) {
|
|
17393
|
+
const clauses = [
|
|
17394
|
+
'"is_deleted" = 0',
|
|
17395
|
+
'"archived_at" is null',
|
|
17396
|
+
`"trust_tier" is not 'quarantined'`,
|
|
17397
|
+
'"superseded_by" is null'
|
|
17398
|
+
];
|
|
17399
|
+
const args = [];
|
|
17400
|
+
if (ctx.userId !== void 0) {
|
|
17401
|
+
clauses.push('"user_id" = ?');
|
|
17402
|
+
args.push(ctx.userId);
|
|
17403
|
+
}
|
|
17404
|
+
return { sql: clauses.join(" and "), args };
|
|
17405
|
+
}
|
|
17406
|
+
async function getVaultCandidateKeysOp(ctx, options) {
|
|
17407
|
+
const mapRaw = (raw) => ({
|
|
17408
|
+
uniqueId: raw.id,
|
|
17409
|
+
folderId: raw.folder_id ?? null,
|
|
17410
|
+
scope: raw.scope ?? "",
|
|
17411
|
+
embeddingModel: raw.embedding_model ?? null,
|
|
17412
|
+
updatedAt: new Date(raw.updated_at)
|
|
17413
|
+
});
|
|
17414
|
+
try {
|
|
17415
|
+
const base = baseVaultSql(ctx);
|
|
17416
|
+
const clauses = [base.sql];
|
|
17417
|
+
const args = [...base.args];
|
|
17418
|
+
if (options?.scopes?.length) {
|
|
17419
|
+
clauses.push(`"scope" in (${options.scopes.map(() => "?").join(",")})`);
|
|
17420
|
+
args.push(...options.scopes);
|
|
17421
|
+
}
|
|
17422
|
+
if (options?.folderId !== void 0) {
|
|
17423
|
+
clauses.push(options.folderId === null ? '"folder_id" is null' : '"folder_id" = ?');
|
|
17424
|
+
if (options.folderId !== null) args.push(options.folderId);
|
|
17425
|
+
}
|
|
17426
|
+
const sql = `select "id", "scope", "folder_id", "embedding_model", "updated_at" from "memory_vault" where ${clauses.join(" and ")}`;
|
|
17427
|
+
const rows = await ctx.vaultMemoryCollection.query(import_watermelondb17.Q.unsafeSqlQuery(sql, args)).unsafeFetchRaw();
|
|
17428
|
+
return rows.map(mapRaw);
|
|
17429
|
+
} catch (err) {
|
|
17430
|
+
getLogger().debug(
|
|
17431
|
+
"memoryVault: getVaultCandidateKeysOp projected SQL unavailable, using full-load fallback: " + (err instanceof Error ? err.message : String(err))
|
|
17432
|
+
);
|
|
17433
|
+
const conditions = [
|
|
17434
|
+
...baseVaultConditions(ctx),
|
|
17435
|
+
...options?.scopes?.length ? [import_watermelondb17.Q.where("scope", import_watermelondb17.Q.oneOf(options.scopes))] : [],
|
|
17436
|
+
...options?.folderId !== void 0 ? [import_watermelondb17.Q.where("folder_id", options.folderId)] : []
|
|
17437
|
+
];
|
|
17438
|
+
const rows = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
|
|
17439
|
+
return rows.map(mapRaw);
|
|
17440
|
+
}
|
|
17441
|
+
}
|
|
17442
|
+
async function getVaultEmbeddingsByIdsOp(ctx, ids) {
|
|
17443
|
+
if (ids.length === 0) return [];
|
|
17444
|
+
const mapRaw = (raw) => ({
|
|
17445
|
+
uniqueId: raw.id,
|
|
17446
|
+
embedding: raw.embedding ?? null,
|
|
17447
|
+
embeddingModel: raw.embedding_model ?? null
|
|
17448
|
+
});
|
|
17449
|
+
try {
|
|
17450
|
+
const base = baseVaultSql(ctx);
|
|
17451
|
+
const sql = `select "id", "embedding", "embedding_model" from "memory_vault" where ${base.sql} and "id" in (${ids.map(() => "?").join(",")})`;
|
|
17452
|
+
const rows = await ctx.vaultMemoryCollection.query(import_watermelondb17.Q.unsafeSqlQuery(sql, [...base.args, ...ids])).unsafeFetchRaw();
|
|
17453
|
+
return rows.map(mapRaw);
|
|
17454
|
+
} catch (err) {
|
|
17455
|
+
getLogger().debug(
|
|
17456
|
+
"memoryVault: getVaultEmbeddingsByIdsOp projected SQL unavailable, using full-load fallback: " + (err instanceof Error ? err.message : String(err))
|
|
17457
|
+
);
|
|
17458
|
+
const rows = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx), import_watermelondb17.Q.where("id", import_watermelondb17.Q.oneOf(ids))).unsafeFetchRaw();
|
|
17459
|
+
return rows.map(mapRaw);
|
|
17460
|
+
}
|
|
17461
|
+
}
|
|
17462
|
+
async function getVaultMemoriesByIdsOp(ctx, ids) {
|
|
17463
|
+
if (ids.length === 0) return [];
|
|
17464
|
+
const conditions = [...baseVaultConditions(ctx), import_watermelondb17.Q.where("id", import_watermelondb17.Q.oneOf(ids))];
|
|
17465
|
+
const results = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
|
|
17466
|
+
return mapInBatches(
|
|
17467
|
+
results,
|
|
17468
|
+
(raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
17469
|
+
);
|
|
17470
|
+
}
|
|
17392
17471
|
async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
17393
17472
|
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
|
|
17394
17473
|
return mapInBatches(results, async (raw) => {
|
|
@@ -17781,6 +17860,7 @@ var init_operations3 = __esm({
|
|
|
17781
17860
|
"src/lib/db/memoryVault/operations.ts"() {
|
|
17782
17861
|
"use strict";
|
|
17783
17862
|
import_watermelondb17 = __toESM(require_watermelondb());
|
|
17863
|
+
init_logger();
|
|
17784
17864
|
init_operations2();
|
|
17785
17865
|
init_encryption2();
|
|
17786
17866
|
KNOWN_TRUST_TIERS = /* @__PURE__ */ new Set(["quarantined", "trusted"]);
|
|
@@ -20579,6 +20659,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
20579
20659
|
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
20580
20660
|
},
|
|
20581
20661
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
20662
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
20582
20663
|
...decomposeAvailable && {
|
|
20583
20664
|
decompose: "llm",
|
|
20584
20665
|
decomposeOptions: options.decomposeOptions
|
|
@@ -21361,80 +21442,97 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
|
|
|
21361
21442
|
);
|
|
21362
21443
|
}
|
|
21363
21444
|
}
|
|
21364
|
-
|
|
21365
|
-
|
|
21366
|
-
|
|
21367
|
-
|
|
21368
|
-
|
|
21369
|
-
return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
|
|
21370
|
-
}
|
|
21371
|
-
const folderId = searchOptions?.folderId;
|
|
21372
|
-
const queryOpts = {};
|
|
21373
|
-
if (scopes?.length) queryOpts.scopes = scopes;
|
|
21374
|
-
if (folderId !== void 0) queryOpts.folderId = folderId;
|
|
21375
|
-
if (searchOptions?.factTypes?.length) queryOpts.factTypes = searchOptions.factTypes;
|
|
21376
|
-
if (searchOptions?.includeArchived) queryOpts.includeArchived = true;
|
|
21377
|
-
const loaded = await getAllVaultMemoriesOp(
|
|
21445
|
+
function admitVaultProjections(queryEmbedding, vectored, k) {
|
|
21446
|
+
return vectored.map((it) => ({ it, score: cosineSimilarity(queryEmbedding, it.embedding) })).sort((a, b) => b.score - a.score || b.it.updatedAt.getTime() - a.it.updatedAt.getTime()).slice(0, k).map((s) => s.it.uniqueId);
|
|
21447
|
+
}
|
|
21448
|
+
async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, queryOpts, opts) {
|
|
21449
|
+
const keys = await getVaultCandidateKeysOp(
|
|
21378
21450
|
vaultCtx,
|
|
21379
21451
|
Object.keys(queryOpts).length > 0 ? queryOpts : void 0
|
|
21380
21452
|
);
|
|
21381
|
-
const
|
|
21382
|
-
if (
|
|
21383
|
-
|
|
21384
|
-
`memoryVault: ${loaded.length - memories.length}/${loaded.length} memories still encrypted (key unavailable?) \u2014 excluded from search`
|
|
21385
|
-
);
|
|
21386
|
-
}
|
|
21387
|
-
if (memories.length === 0) {
|
|
21388
|
-
return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
|
|
21453
|
+
const vaultSize = keys.length;
|
|
21454
|
+
if (keys.length === 0) {
|
|
21455
|
+
return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
|
|
21389
21456
|
}
|
|
21390
21457
|
const queryEmbedding = await generateEmbedding(query, embeddingOptions);
|
|
21391
21458
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21392
|
-
const
|
|
21393
|
-
const
|
|
21394
|
-
|
|
21395
|
-
|
|
21396
|
-
|
|
21397
|
-
const
|
|
21398
|
-
|
|
21399
|
-
|
|
21400
|
-
|
|
21401
|
-
|
|
21402
|
-
const modelCompatible = (
|
|
21403
|
-
if (
|
|
21459
|
+
const vectored = [];
|
|
21460
|
+
const missIds = [];
|
|
21461
|
+
const noVectorIds = [];
|
|
21462
|
+
const keyById = new Map(keys.map((k2) => [k2.uniqueId, k2]));
|
|
21463
|
+
for (const k2 of keys) {
|
|
21464
|
+
const cached = cache.get(k2.uniqueId);
|
|
21465
|
+
if (cached && cached.length === queryEmbedding.length) {
|
|
21466
|
+
vectored.push({ uniqueId: k2.uniqueId, embedding: cached, updatedAt: k2.updatedAt });
|
|
21467
|
+
continue;
|
|
21468
|
+
}
|
|
21469
|
+
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
21470
|
+
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
21471
|
+
else noVectorIds.push(k2.uniqueId);
|
|
21472
|
+
}
|
|
21473
|
+
if (missIds.length > 0) {
|
|
21474
|
+
const rows = await getVaultEmbeddingsByIdsOp(vaultCtx, missIds);
|
|
21475
|
+
const gotVector = /* @__PURE__ */ new Set();
|
|
21476
|
+
for (const r of rows) {
|
|
21477
|
+
if (!r.embedding) continue;
|
|
21404
21478
|
try {
|
|
21405
|
-
const parsed = JSON.parse(
|
|
21479
|
+
const parsed = JSON.parse(r.embedding);
|
|
21406
21480
|
if (Array.isArray(parsed) && parsed.length === queryEmbedding.length) {
|
|
21407
|
-
|
|
21408
|
-
|
|
21481
|
+
const vec = Float32Array.from(parsed);
|
|
21482
|
+
cache.set(r.uniqueId, vec);
|
|
21483
|
+
const k2 = keyById.get(r.uniqueId);
|
|
21484
|
+
vectored.push({ uniqueId: r.uniqueId, embedding: vec, updatedAt: k2.updatedAt });
|
|
21485
|
+
gotVector.add(r.uniqueId);
|
|
21409
21486
|
}
|
|
21410
21487
|
} catch {
|
|
21411
21488
|
}
|
|
21412
21489
|
}
|
|
21413
|
-
|
|
21414
|
-
uncachedTexts.push(content);
|
|
21415
|
-
uncachedIndices.push(i);
|
|
21490
|
+
for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
|
|
21416
21491
|
}
|
|
21417
|
-
if (
|
|
21418
|
-
|
|
21419
|
-
|
|
21492
|
+
if (noVectorIds.length > 0) {
|
|
21493
|
+
const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
|
|
21494
|
+
if (noVectorIds.length > laneIds.length) {
|
|
21495
|
+
getLogger().warn(
|
|
21496
|
+
`memoryVault: projected search un-embedded lane capped at ${laneIds.length}/${noVectorIds.length}`
|
|
21497
|
+
);
|
|
21498
|
+
}
|
|
21499
|
+
const laneRows = (await getVaultMemoriesByIdsOp(vaultCtx, laneIds)).filter(
|
|
21500
|
+
(m) => !isEncrypted(m.content)
|
|
21420
21501
|
);
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
|
|
21426
|
-
updateVaultMemoryEmbeddingOp(
|
|
21427
|
-
vaultCtx,
|
|
21428
|
-
memories[uncachedIndices[j]].uniqueId,
|
|
21429
|
-
JSON.stringify(newEmbeddings[j]),
|
|
21430
|
-
currentModel
|
|
21431
|
-
).catch(
|
|
21432
|
-
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
21433
|
-
() => {
|
|
21434
|
-
}
|
|
21502
|
+
if (laneRows.length > 0) {
|
|
21503
|
+
const laneVecs = await generateEmbeddings(
|
|
21504
|
+
laneRows.map((m) => m.content),
|
|
21505
|
+
embeddingOptions
|
|
21435
21506
|
);
|
|
21507
|
+
laneRows.forEach((m, i) => {
|
|
21508
|
+
const vec = Float32Array.from(laneVecs[i]);
|
|
21509
|
+
cache.set(m.uniqueId, vec);
|
|
21510
|
+
vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
|
|
21511
|
+
updateVaultMemoryEmbeddingOp(
|
|
21512
|
+
vaultCtx,
|
|
21513
|
+
m.uniqueId,
|
|
21514
|
+
JSON.stringify(laneVecs[i]),
|
|
21515
|
+
currentModel
|
|
21516
|
+
).catch(() => {
|
|
21517
|
+
});
|
|
21518
|
+
});
|
|
21436
21519
|
}
|
|
21437
21520
|
}
|
|
21521
|
+
const k = Math.max(opts.limit * opts.admitFactor, opts.admitFloor);
|
|
21522
|
+
const admittedIds = admitVaultProjections(queryEmbedding, vectored, k);
|
|
21523
|
+
const admissionSet = new Set(admittedIds);
|
|
21524
|
+
if (opts.forceIncludeIds) {
|
|
21525
|
+
for (const id of opts.forceIncludeIds) {
|
|
21526
|
+
if (keyById.has(id)) admissionSet.add(id);
|
|
21527
|
+
}
|
|
21528
|
+
}
|
|
21529
|
+
const admittedRows = await getVaultMemoriesByIdsOp(vaultCtx, [...admissionSet]);
|
|
21530
|
+
const memories = admittedRows.filter((m) => !isEncrypted(m.content));
|
|
21531
|
+
if (memories.length < admittedRows.length) {
|
|
21532
|
+
getLogger().warn(
|
|
21533
|
+
`memoryVault: ${admittedRows.length - memories.length}/${admittedRows.length} admitted memories still encrypted (key unavailable?) \u2014 excluded from projected search`
|
|
21534
|
+
);
|
|
21535
|
+
}
|
|
21438
21536
|
const embeddedItems = memories.map((m) => ({
|
|
21439
21537
|
id: m.uniqueId,
|
|
21440
21538
|
content: m.content,
|
|
@@ -21449,6 +21547,125 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
21449
21547
|
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
21450
21548
|
factType: m.factType
|
|
21451
21549
|
}));
|
|
21550
|
+
return { memories, embeddedItems, queryEmbedding, vaultSize };
|
|
21551
|
+
}
|
|
21552
|
+
async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
21553
|
+
const limit = searchOptions?.limit ?? 5;
|
|
21554
|
+
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
21555
|
+
const scopes = searchOptions?.scopes;
|
|
21556
|
+
if (!query || typeof query !== "string") {
|
|
21557
|
+
return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
|
|
21558
|
+
}
|
|
21559
|
+
const folderId = searchOptions?.folderId;
|
|
21560
|
+
const queryOpts = {};
|
|
21561
|
+
if (scopes?.length) queryOpts.scopes = scopes;
|
|
21562
|
+
if (folderId !== void 0) queryOpts.folderId = folderId;
|
|
21563
|
+
if (searchOptions?.factTypes?.length) queryOpts.factTypes = searchOptions.factTypes;
|
|
21564
|
+
if (searchOptions?.includeArchived) queryOpts.includeArchived = true;
|
|
21565
|
+
const ADMIT_FACTOR = searchOptions?.admitFactor ?? 3;
|
|
21566
|
+
const ADMIT_FLOOR = searchOptions?.admitFloor ?? 30;
|
|
21567
|
+
const UNEMBEDDED_CAP = 200;
|
|
21568
|
+
let memories;
|
|
21569
|
+
let embeddedItems;
|
|
21570
|
+
let queryEmbedding;
|
|
21571
|
+
let vaultSize;
|
|
21572
|
+
if (searchOptions?.decryptLast) {
|
|
21573
|
+
const forceIncludeIds = [
|
|
21574
|
+
...searchOptions.entityRanking ?? [],
|
|
21575
|
+
...searchOptions.temporalRanking ?? []
|
|
21576
|
+
];
|
|
21577
|
+
const corpus = await buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, queryOpts, {
|
|
21578
|
+
limit,
|
|
21579
|
+
admitFactor: ADMIT_FACTOR,
|
|
21580
|
+
admitFloor: ADMIT_FLOOR,
|
|
21581
|
+
unembeddedCap: UNEMBEDDED_CAP,
|
|
21582
|
+
...forceIncludeIds.length > 0 && { forceIncludeIds }
|
|
21583
|
+
});
|
|
21584
|
+
if (corpus.vaultSize === 0) {
|
|
21585
|
+
return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
|
|
21586
|
+
}
|
|
21587
|
+
({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
|
|
21588
|
+
if (memories.length === 0) {
|
|
21589
|
+
return { results: [], vaultSize, reranked: false, hadV2Head: false };
|
|
21590
|
+
}
|
|
21591
|
+
} else {
|
|
21592
|
+
const loaded = await getAllVaultMemoriesOp(
|
|
21593
|
+
vaultCtx,
|
|
21594
|
+
Object.keys(queryOpts).length > 0 ? queryOpts : void 0
|
|
21595
|
+
);
|
|
21596
|
+
vaultSize = loaded.length;
|
|
21597
|
+
memories = loaded.filter((m) => !isEncrypted(m.content));
|
|
21598
|
+
if (memories.length < loaded.length) {
|
|
21599
|
+
getLogger().warn(
|
|
21600
|
+
`memoryVault: ${loaded.length - memories.length}/${loaded.length} memories still encrypted (key unavailable?) \u2014 excluded from search`
|
|
21601
|
+
);
|
|
21602
|
+
}
|
|
21603
|
+
if (memories.length === 0) {
|
|
21604
|
+
return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
|
|
21605
|
+
}
|
|
21606
|
+
queryEmbedding = await generateEmbedding(query, embeddingOptions);
|
|
21607
|
+
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21608
|
+
const uncachedTexts = [];
|
|
21609
|
+
const uncachedIndices = [];
|
|
21610
|
+
let staleReembedCount = 0;
|
|
21611
|
+
for (let i = 0; i < memories.length; i++) {
|
|
21612
|
+
const content = memories[i].content;
|
|
21613
|
+
const memoryId = memories[i].uniqueId;
|
|
21614
|
+
const cached = cache.get(memoryId);
|
|
21615
|
+
if (cached && cached.length === queryEmbedding.length) continue;
|
|
21616
|
+
if (cached) cache.delete(memoryId);
|
|
21617
|
+
const storedModel = memories[i].embeddingModel;
|
|
21618
|
+
const modelCompatible = (storedModel ?? currentModel) === currentModel;
|
|
21619
|
+
if (memories[i].embedding && modelCompatible) {
|
|
21620
|
+
try {
|
|
21621
|
+
const parsed = JSON.parse(memories[i].embedding);
|
|
21622
|
+
if (Array.isArray(parsed) && parsed.length === queryEmbedding.length) {
|
|
21623
|
+
cache.set(memoryId, Float32Array.from(parsed));
|
|
21624
|
+
continue;
|
|
21625
|
+
}
|
|
21626
|
+
} catch {
|
|
21627
|
+
}
|
|
21628
|
+
}
|
|
21629
|
+
if (memories[i].embedding && !modelCompatible) staleReembedCount++;
|
|
21630
|
+
uncachedTexts.push(content);
|
|
21631
|
+
uncachedIndices.push(i);
|
|
21632
|
+
}
|
|
21633
|
+
if (staleReembedCount > 0) {
|
|
21634
|
+
getLogger().warn(
|
|
21635
|
+
`memoryVault: re-embedding ${staleReembedCount} memories whose stored embedding model differs from the current model (${currentModel}) \u2014 embedding-model change detected`
|
|
21636
|
+
);
|
|
21637
|
+
}
|
|
21638
|
+
if (uncachedTexts.length > 0) {
|
|
21639
|
+
const newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
|
|
21640
|
+
for (let j = 0; j < uncachedTexts.length; j++) {
|
|
21641
|
+
cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
|
|
21642
|
+
updateVaultMemoryEmbeddingOp(
|
|
21643
|
+
vaultCtx,
|
|
21644
|
+
memories[uncachedIndices[j]].uniqueId,
|
|
21645
|
+
JSON.stringify(newEmbeddings[j]),
|
|
21646
|
+
currentModel
|
|
21647
|
+
).catch(
|
|
21648
|
+
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
21649
|
+
() => {
|
|
21650
|
+
}
|
|
21651
|
+
);
|
|
21652
|
+
}
|
|
21653
|
+
}
|
|
21654
|
+
embeddedItems = memories.map((m) => ({
|
|
21655
|
+
id: m.uniqueId,
|
|
21656
|
+
content: m.content,
|
|
21657
|
+
embedding: cache.get(m.uniqueId) ?? [],
|
|
21658
|
+
createdAt: m.createdAt,
|
|
21659
|
+
updatedAt: m.updatedAt,
|
|
21660
|
+
proofCount: m.proofCount,
|
|
21661
|
+
lastObservedAt: m.lastObservedAt,
|
|
21662
|
+
eventTimeStart: m.eventTimeStart,
|
|
21663
|
+
sourceChunkIds: m.sourceChunkIds,
|
|
21664
|
+
eventTimeEnd: m.eventTimeEnd,
|
|
21665
|
+
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
21666
|
+
factType: m.factType
|
|
21667
|
+
}));
|
|
21668
|
+
}
|
|
21452
21669
|
if (queryEmbedding.length > 0) {
|
|
21453
21670
|
const mismatched = embeddedItems.filter(
|
|
21454
21671
|
(it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
|
|
@@ -21534,7 +21751,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
21534
21751
|
});
|
|
21535
21752
|
return stampTimestamps({
|
|
21536
21753
|
results: composite,
|
|
21537
|
-
vaultSize
|
|
21754
|
+
vaultSize,
|
|
21538
21755
|
reranked: rerankStats.applied,
|
|
21539
21756
|
hadV2Head: v2HeadStats.hadResults
|
|
21540
21757
|
});
|
|
@@ -21559,7 +21776,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
21559
21776
|
});
|
|
21560
21777
|
return stampTimestamps({
|
|
21561
21778
|
results: results2,
|
|
21562
|
-
vaultSize
|
|
21779
|
+
vaultSize,
|
|
21563
21780
|
reranked: rerankStats.applied,
|
|
21564
21781
|
hadV2Head: v2HeadStats.hadResults
|
|
21565
21782
|
});
|
|
@@ -21572,7 +21789,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
21572
21789
|
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
21573
21790
|
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
21574
21791
|
});
|
|
21575
|
-
return stampTimestamps({ results: results2, vaultSize
|
|
21792
|
+
return stampTimestamps({ results: results2, vaultSize, hadV2Head: results2.length > 0 });
|
|
21576
21793
|
}
|
|
21577
21794
|
const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
21578
21795
|
limit,
|
|
@@ -21584,7 +21801,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
21584
21801
|
supersessionWindow: searchOptions.supersessionWindow
|
|
21585
21802
|
}
|
|
21586
21803
|
});
|
|
21587
|
-
return stampTimestamps({ results, vaultSize
|
|
21804
|
+
return stampTimestamps({ results, vaultSize, hadV2Head: results.length > 0 });
|
|
21588
21805
|
}
|
|
21589
21806
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
21590
21807
|
const { results } = await searchVaultMemoriesWithSize(
|
|
@@ -28244,9 +28461,11 @@ function createAutoExtractor(options) {
|
|
|
28244
28461
|
}
|
|
28245
28462
|
}
|
|
28246
28463
|
);
|
|
28247
|
-
|
|
28248
|
-
|
|
28249
|
-
|
|
28464
|
+
if (outcome !== "empty-after-retry") {
|
|
28465
|
+
const advancedTo = window2[window2.length - 1].id;
|
|
28466
|
+
stateFor(conversationId).watermark = advancedTo;
|
|
28467
|
+
persistCursor(conversationId, messages, advancedTo, contiguous);
|
|
28468
|
+
}
|
|
28250
28469
|
for (let i = 0; i < results.length; i++) {
|
|
28251
28470
|
if (results[i].action === "suppressed") continue;
|
|
28252
28471
|
options.onMemoryExtracted?.({
|
package/dist/server/index.d.mts
CHANGED
|
@@ -4793,6 +4793,18 @@ interface MemoryVaultSearchOptions {
|
|
|
4793
4793
|
* pass-through from `recall()` when the query has a temporal phrase.
|
|
4794
4794
|
*/
|
|
4795
4795
|
temporalRanking?: string[];
|
|
4796
|
+
/**
|
|
4797
|
+
* B2 decrypt-last — when set, build the ranking corpus from a
|
|
4798
|
+
* column-projected key scan + vector LRU (no whole-vault blob load),
|
|
4799
|
+
* decrypting content only for the admission window via
|
|
4800
|
+
* {@link buildProjectedCorpus}. Default OFF: the legacy whole-vault
|
|
4801
|
+
* prefix stays byte-identical.
|
|
4802
|
+
*/
|
|
4803
|
+
decryptLast?: boolean;
|
|
4804
|
+
/** Admission window multiplier for decrypt-last (`limit * admitFactor`). Default 3. */
|
|
4805
|
+
admitFactor?: number;
|
|
4806
|
+
/** Admission window floor for decrypt-last. Default 30. */
|
|
4807
|
+
admitFloor?: number;
|
|
4796
4808
|
}
|
|
4797
4809
|
/**
|
|
4798
4810
|
* Pre-embed all vault memories that are not yet in the cache.
|
|
@@ -5073,6 +5085,13 @@ interface RecallOptions {
|
|
|
5073
5085
|
bm25AdmissionDivisor?: number;
|
|
5074
5086
|
/** RRF smoothing constant for lane fusion (facts × chunks and side lanes). Default: 60. */
|
|
5075
5087
|
rrfK?: number;
|
|
5088
|
+
/**
|
|
5089
|
+
* Decrypt vault memory content only for the top-N ranked candidates
|
|
5090
|
+
* instead of the whole vault. Forwarded verbatim to the vault search
|
|
5091
|
+
* pipeline's `MemoryVaultSearchOptions`. Default: off (legacy
|
|
5092
|
+
* whole-vault decrypt path).
|
|
5093
|
+
*/
|
|
5094
|
+
decryptLast?: boolean;
|
|
5076
5095
|
/** Total graph hops incl. the seed lookup (hop 1). Default: 1 (seed only). */
|
|
5077
5096
|
maxHops?: number;
|
|
5078
5097
|
/** Max neighbor entities expanded per hop. Default: 8. */
|
|
@@ -6943,6 +6962,12 @@ declare function createMemoryVaultTool(vaultCtx: VaultMemoryOperationsContext, o
|
|
|
6943
6962
|
* during a busy window are still examined instead of scrolling out of a last-N
|
|
6944
6963
|
* window.
|
|
6945
6964
|
*
|
|
6965
|
+
* The watermark advances only when the extractor genuinely EXAMINED the window.
|
|
6966
|
+
* A pipeline throw and an `empty-after-retry` outcome (the extraction LLM
|
|
6967
|
+
* returned empty/malformed after exhausting its retries) both leave it in place,
|
|
6968
|
+
* so the next turn's window re-covers those messages instead of stranding them.
|
|
6969
|
+
* A quiet turn that legitimately yielded no facts *does* advance it.
|
|
6970
|
+
*
|
|
6946
6971
|
* Durability: the in-memory watermark alone does NOT survive process death, so
|
|
6947
6972
|
* a session killed after messages accumulate but before extraction would, on
|
|
6948
6973
|
* the next launch, fall back to a trailing-window guess and could skip the
|
package/dist/server/index.d.ts
CHANGED
|
@@ -4793,6 +4793,18 @@ interface MemoryVaultSearchOptions {
|
|
|
4793
4793
|
* pass-through from `recall()` when the query has a temporal phrase.
|
|
4794
4794
|
*/
|
|
4795
4795
|
temporalRanking?: string[];
|
|
4796
|
+
/**
|
|
4797
|
+
* B2 decrypt-last — when set, build the ranking corpus from a
|
|
4798
|
+
* column-projected key scan + vector LRU (no whole-vault blob load),
|
|
4799
|
+
* decrypting content only for the admission window via
|
|
4800
|
+
* {@link buildProjectedCorpus}. Default OFF: the legacy whole-vault
|
|
4801
|
+
* prefix stays byte-identical.
|
|
4802
|
+
*/
|
|
4803
|
+
decryptLast?: boolean;
|
|
4804
|
+
/** Admission window multiplier for decrypt-last (`limit * admitFactor`). Default 3. */
|
|
4805
|
+
admitFactor?: number;
|
|
4806
|
+
/** Admission window floor for decrypt-last. Default 30. */
|
|
4807
|
+
admitFloor?: number;
|
|
4796
4808
|
}
|
|
4797
4809
|
/**
|
|
4798
4810
|
* Pre-embed all vault memories that are not yet in the cache.
|
|
@@ -5073,6 +5085,13 @@ interface RecallOptions {
|
|
|
5073
5085
|
bm25AdmissionDivisor?: number;
|
|
5074
5086
|
/** RRF smoothing constant for lane fusion (facts × chunks and side lanes). Default: 60. */
|
|
5075
5087
|
rrfK?: number;
|
|
5088
|
+
/**
|
|
5089
|
+
* Decrypt vault memory content only for the top-N ranked candidates
|
|
5090
|
+
* instead of the whole vault. Forwarded verbatim to the vault search
|
|
5091
|
+
* pipeline's `MemoryVaultSearchOptions`. Default: off (legacy
|
|
5092
|
+
* whole-vault decrypt path).
|
|
5093
|
+
*/
|
|
5094
|
+
decryptLast?: boolean;
|
|
5076
5095
|
/** Total graph hops incl. the seed lookup (hop 1). Default: 1 (seed only). */
|
|
5077
5096
|
maxHops?: number;
|
|
5078
5097
|
/** Max neighbor entities expanded per hop. Default: 8. */
|
|
@@ -6943,6 +6962,12 @@ declare function createMemoryVaultTool(vaultCtx: VaultMemoryOperationsContext, o
|
|
|
6943
6962
|
* during a busy window are still examined instead of scrolling out of a last-N
|
|
6944
6963
|
* window.
|
|
6945
6964
|
*
|
|
6965
|
+
* The watermark advances only when the extractor genuinely EXAMINED the window.
|
|
6966
|
+
* A pipeline throw and an `empty-after-retry` outcome (the extraction LLM
|
|
6967
|
+
* returned empty/malformed after exhausting its retries) both leave it in place,
|
|
6968
|
+
* so the next turn's window re-covers those messages instead of stranding them.
|
|
6969
|
+
* A quiet turn that legitimately yielded no facts *does* advance it.
|
|
6970
|
+
*
|
|
6946
6971
|
* Durability: the in-memory watermark alone does NOT survive process death, so
|
|
6947
6972
|
* a session killed after messages accumulate but before extraction would, on
|
|
6948
6973
|
* the next launch, fall back to a trailing-window guess and could skip the
|
package/dist/server/index.mjs
CHANGED
|
@@ -125,7 +125,7 @@ import {
|
|
|
125
125
|
updateVaultMemoryOp,
|
|
126
126
|
upsertMessageOp,
|
|
127
127
|
vaultMemoryToStored
|
|
128
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-QC4WHNIJ.mjs";
|
|
129
129
|
import {
|
|
130
130
|
createStreamingDeAnonymizer,
|
|
131
131
|
resolvePiiRedactor
|
|
@@ -6141,9 +6141,11 @@ function createAutoExtractor(options) {
|
|
|
6141
6141
|
}
|
|
6142
6142
|
}
|
|
6143
6143
|
);
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6144
|
+
if (outcome !== "empty-after-retry") {
|
|
6145
|
+
const advancedTo = window2[window2.length - 1].id;
|
|
6146
|
+
stateFor(conversationId).watermark = advancedTo;
|
|
6147
|
+
persistCursor(conversationId, messages, advancedTo, contiguous);
|
|
6148
|
+
}
|
|
6147
6149
|
for (let i = 0; i < results.length; i++) {
|
|
6148
6150
|
if (results[i].action === "suppressed") continue;
|
|
6149
6151
|
options.onMemoryExtracted?.({
|