@anuma/sdk 3.8.5 → 3.9.1

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.
@@ -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
- async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
21365
- const limit = searchOptions?.limit ?? 5;
21366
- const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
21367
- const scopes = searchOptions?.scopes;
21368
- if (!query || typeof query !== "string") {
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 memories = loaded.filter((m) => !isEncrypted(m.content));
21382
- if (memories.length < loaded.length) {
21383
- getLogger().warn(
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 uncachedTexts = [];
21393
- const uncachedIndices = [];
21394
- let staleReembedCount = 0;
21395
- for (let i = 0; i < memories.length; i++) {
21396
- const content = memories[i].content;
21397
- const memoryId = memories[i].uniqueId;
21398
- const cached = cache.get(memoryId);
21399
- if (cached && cached.length === queryEmbedding.length) continue;
21400
- if (cached) cache.delete(memoryId);
21401
- const storedModel = memories[i].embeddingModel;
21402
- const modelCompatible = (storedModel ?? currentModel) === currentModel;
21403
- if (memories[i].embedding && modelCompatible) {
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(memories[i].embedding);
21479
+ const parsed = JSON.parse(r.embedding);
21406
21480
  if (Array.isArray(parsed) && parsed.length === queryEmbedding.length) {
21407
- cache.set(memoryId, Float32Array.from(parsed));
21408
- continue;
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
- if (memories[i].embedding && !modelCompatible) staleReembedCount++;
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 (staleReembedCount > 0) {
21418
- getLogger().warn(
21419
- `memoryVault: re-embedding ${staleReembedCount} memories whose stored embedding model differs from the current model (${currentModel}) \u2014 embedding-model change detected`
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
- if (uncachedTexts.length > 0) {
21423
- const newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
21424
- for (let j = 0; j < uncachedTexts.length; j++) {
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: loaded.length,
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: loaded.length,
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: loaded.length, hadV2Head: results2.length > 0 });
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: loaded.length, hadV2Head: results.length > 0 });
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(
@@ -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. */
@@ -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. */
@@ -125,7 +125,7 @@ import {
125
125
  updateVaultMemoryOp,
126
126
  upsertMessageOp,
127
127
  vaultMemoryToStored
128
- } from "./chunk-FS56IDOW.mjs";
128
+ } from "./chunk-QC4WHNIJ.mjs";
129
129
  import {
130
130
  createStreamingDeAnonymizer,
131
131
  resolvePiiRedactor
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-FS56IDOW.mjs";
3
+ } from "./chunk-QC4WHNIJ.mjs";
4
4
  import "./chunk-MIXEASUP.mjs";
5
5
  import "./chunk-3RPGXXPZ.mjs";
6
6
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "3.8.5",
3
+ "version": "3.9.1",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -156,7 +156,7 @@
156
156
  "homepage": "https://github.com/anuma-ai/sdk#readme",
157
157
  "packageManager": "pnpm@10.23.0",
158
158
  "dependencies": {
159
- "@anuma/portal": "1.0.0-next.20260724050535",
159
+ "@anuma/portal": "1.0.0-next.20260724210432",
160
160
  "@babel/parser": "^7.29.2",
161
161
  "@babel/types": "^7.29.0",
162
162
  "ai": "6.0.202",