@anuma/sdk 6.0.1 → 6.1.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.
@@ -6103,6 +6103,7 @@ function admitVaultProjections(queryEmbedding, vectored, k) {
6103
6103
  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);
6104
6104
  }
6105
6105
  async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, queryOpts, opts) {
6106
+ let rowsDecrypted = 0;
6106
6107
  const keys = await getVaultCandidateKeysOp(
6107
6108
  vaultCtx,
6108
6109
  Object.keys(queryOpts).length > 0 ? queryOpts : void 0
@@ -6115,7 +6116,8 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
6115
6116
  embeddedItems: [],
6116
6117
  queryEmbedding: [],
6117
6118
  vaultSize: 0,
6118
- laneEmbedFailed: false
6119
+ laneEmbedFailed: false,
6120
+ rowsDecrypted: 0
6119
6121
  };
6120
6122
  }
6121
6123
  const queryEmbedding = await embedQueryOrDegrade(
@@ -6161,6 +6163,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
6161
6163
  for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
6162
6164
  }
6163
6165
  let laneEmbedFailed = false;
6166
+ const laneById = /* @__PURE__ */ new Map();
6164
6167
  if (noVectorIds.length > 0) {
6165
6168
  const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
6166
6169
  if (noVectorIds.length > laneIds.length) {
@@ -6168,9 +6171,10 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
6168
6171
  `memoryVault: projected search un-embedded lane capped at ${laneIds.length}/${noVectorIds.length}`
6169
6172
  );
6170
6173
  }
6171
- const laneRows = (await getVaultMemoriesByIdsOp(vaultCtx, laneIds, hydrateOpts)).filter(
6172
- (m) => !isEncrypted(m.content)
6173
- );
6174
+ const laneFetched = await getVaultMemoriesByIdsOp(vaultCtx, laneIds, hydrateOpts);
6175
+ rowsDecrypted += laneFetched.length;
6176
+ for (const row of laneFetched) laneById.set(row.uniqueId, row);
6177
+ const laneRows = laneFetched.filter((m) => !isEncrypted(m.content));
6174
6178
  if (laneRows.length > 0) {
6175
6179
  let laneVecs;
6176
6180
  try {
@@ -6216,7 +6220,16 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
6216
6220
  if (keyById.has(id)) admissionSet.add(id);
6217
6221
  }
6218
6222
  }
6219
- const admittedRows = await getVaultMemoriesByIdsOp(vaultCtx, [...admissionSet], hydrateOpts);
6223
+ const idsToFetch = [...admissionSet].filter((id) => !laneById.has(id));
6224
+ const fetched = idsToFetch.length > 0 ? await getVaultMemoriesByIdsOp(vaultCtx, idsToFetch, hydrateOpts) : [];
6225
+ rowsDecrypted += fetched.length;
6226
+ const admittedRows = [
6227
+ ...fetched,
6228
+ ...[...admissionSet].flatMap((id) => {
6229
+ const reused = laneById.get(id);
6230
+ return reused ? [reused] : [];
6231
+ })
6232
+ ];
6220
6233
  const memories = admittedRows.filter((m) => !isEncrypted(m.content));
6221
6234
  if (memories.length < admittedRows.length) {
6222
6235
  getLogger().warn(
@@ -6237,7 +6250,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
6237
6250
  eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
6238
6251
  factType: m.factType
6239
6252
  }));
6240
- return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed };
6253
+ return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed, rowsDecrypted };
6241
6254
  }
6242
6255
  async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
6243
6256
  if (!query || typeof query !== "string") {
@@ -6247,7 +6260,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6247
6260
  queryEmbedding: [],
6248
6261
  vaultSize: 0,
6249
6262
  embeddingsUnavailable: false,
6250
- embeddingFailure: false
6263
+ embeddingFailure: false,
6264
+ decryptLast: !!searchOptions?.decryptLast,
6265
+ rowsDecrypted: 0
6251
6266
  };
6252
6267
  }
6253
6268
  const limit = searchOptions?.limit ?? 5;
@@ -6265,6 +6280,7 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6265
6280
  let embeddedItems;
6266
6281
  let queryEmbedding;
6267
6282
  let vaultSize;
6283
+ let rowsDecrypted;
6268
6284
  let embeddingsUnavailable = false;
6269
6285
  let embeddingFailure = false;
6270
6286
  const onEmbeddingDegraded = () => {
@@ -6291,10 +6307,13 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6291
6307
  queryEmbedding: [],
6292
6308
  vaultSize: 0,
6293
6309
  embeddingsUnavailable: false,
6294
- embeddingFailure: false
6310
+ embeddingFailure: false,
6311
+ decryptLast: true,
6312
+ rowsDecrypted: corpus.rowsDecrypted
6295
6313
  };
6296
6314
  }
6297
6315
  ({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
6316
+ rowsDecrypted = corpus.rowsDecrypted;
6298
6317
  if (corpus.laneEmbedFailed) embeddingFailure = true;
6299
6318
  if (memories.length === 0) {
6300
6319
  return {
@@ -6303,7 +6322,11 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6303
6322
  queryEmbedding: [],
6304
6323
  vaultSize,
6305
6324
  embeddingsUnavailable,
6306
- embeddingFailure
6325
+ embeddingFailure,
6326
+ decryptLast: true,
6327
+ // Rows WERE decrypt-attempted even though none came back readable — that
6328
+ // is the whole point of reporting attempts rather than successes.
6329
+ rowsDecrypted: corpus.rowsDecrypted
6307
6330
  };
6308
6331
  }
6309
6332
  } else {
@@ -6312,6 +6335,7 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6312
6335
  Object.keys(queryOpts).length > 0 ? queryOpts : void 0
6313
6336
  );
6314
6337
  vaultSize = loaded.length;
6338
+ rowsDecrypted = loaded.length;
6315
6339
  memories = loaded.filter((m) => !isEncrypted(m.content));
6316
6340
  if (memories.length < loaded.length) {
6317
6341
  getLogger().warn(
@@ -6325,7 +6349,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6325
6349
  queryEmbedding: [],
6326
6350
  vaultSize: loaded.length,
6327
6351
  embeddingsUnavailable: false,
6328
- embeddingFailure: false
6352
+ embeddingFailure: false,
6353
+ decryptLast: false,
6354
+ rowsDecrypted: loaded.length
6329
6355
  };
6330
6356
  }
6331
6357
  queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
@@ -6410,7 +6436,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
6410
6436
  queryEmbedding,
6411
6437
  vaultSize,
6412
6438
  embeddingsUnavailable,
6413
- embeddingFailure
6439
+ embeddingFailure,
6440
+ decryptLast: !!searchOptions?.decryptLast,
6441
+ rowsDecrypted
6414
6442
  };
6415
6443
  }
6416
6444
  async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
@@ -6578,7 +6606,11 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6578
6606
  reranked: false,
6579
6607
  hadV2Head: false,
6580
6608
  embeddingsUnavailable: false,
6581
- rankedOnCosine: false
6609
+ rankedOnCosine: false,
6610
+ // No storage read happened, so nothing was decrypted; report the path the
6611
+ // caller asked for so this turn is still attributable.
6612
+ decryptLast: !!searchOptions?.decryptLast,
6613
+ rowsDecrypted: 0
6582
6614
  };
6583
6615
  }
6584
6616
  if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
@@ -6601,7 +6633,9 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6601
6633
  reranked: false,
6602
6634
  hadV2Head: false,
6603
6635
  embeddingsUnavailable: prepared.embeddingsUnavailable,
6604
- rankedOnCosine: false
6636
+ rankedOnCosine: false,
6637
+ decryptLast: prepared.decryptLast,
6638
+ rowsDecrypted: prepared.rowsDecrypted
6605
6639
  };
6606
6640
  }
6607
6641
  if (prepared.memories.length === 0) {
@@ -6611,7 +6645,9 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6611
6645
  reranked: false,
6612
6646
  hadV2Head: false,
6613
6647
  embeddingsUnavailable: prepared.embeddingsUnavailable,
6614
- rankedOnCosine: false
6648
+ rankedOnCosine: false,
6649
+ decryptLast: prepared.decryptLast,
6650
+ rowsDecrypted: prepared.rowsDecrypted
6615
6651
  };
6616
6652
  }
6617
6653
  const ranked = await rankPreparedVaultCandidates(
@@ -6620,7 +6656,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6620
6656
  embeddingOptions,
6621
6657
  searchOptions
6622
6658
  );
6623
- return { ...ranked, rankedOnCosine: !ranked.embeddingsUnavailable };
6659
+ return {
6660
+ ...ranked,
6661
+ rankedOnCosine: !ranked.embeddingsUnavailable,
6662
+ decryptLast: prepared.decryptLast,
6663
+ rowsDecrypted: prepared.rowsDecrypted
6664
+ };
6624
6665
  }
6625
6666
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
6626
6667
  const { results } = await searchVaultMemoriesWithSize(
@@ -6724,7 +6765,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
6724
6765
  subQueries = decomp.subQueries;
6725
6766
  }
6726
6767
  }
6727
- const { recall: recall2 } = await import("./recall-OKP4SCC4.mjs");
6768
+ const { recall: recall2 } = await import("./recall-KOKU2PPN.mjs");
6728
6769
  let recallDegraded = [];
6729
6770
  const result = await recall2(
6730
6771
  query,
@@ -7309,6 +7350,8 @@ async function recall(query, ctx, options = {}) {
7309
7350
  let embeddingsUnavailable = false;
7310
7351
  let chunkEmbedFailed = false;
7311
7352
  let factLaneRankedOnCosine = false;
7353
+ let decryptLastRan;
7354
+ let vaultRowsDecrypted;
7312
7355
  const emitDiagnostics = (candidateCount) => {
7313
7356
  const cb = options.onDiagnostics;
7314
7357
  if (!cb) return;
@@ -7325,6 +7368,8 @@ async function recall(query, ctx, options = {}) {
7325
7368
  reranked: didRerank,
7326
7369
  candidateCount,
7327
7370
  ...vaultSize !== void 0 && { vaultSize },
7371
+ ...decryptLastRan !== void 0 && { decryptLast: decryptLastRan },
7372
+ ...vaultRowsDecrypted !== void 0 && { vaultRowsDecrypted },
7328
7373
  factCount: factResults.length,
7329
7374
  chunkCount: chunkResults.length,
7330
7375
  timings: {
@@ -7396,7 +7441,9 @@ async function recall(query, ctx, options = {}) {
7396
7441
  reranked,
7397
7442
  hadV2Head: v2Head,
7398
7443
  embeddingsUnavailable: factEmbeddingsUnavailable,
7399
- rankedOnCosine: factRankedOnCosine
7444
+ rankedOnCosine: factRankedOnCosine,
7445
+ decryptLast: factDecryptLast,
7446
+ rowsDecrypted: factRowsDecrypted
7400
7447
  } = await searchVaultMemoriesWithSize(
7401
7448
  query,
7402
7449
  ctx.vaultCtx,
@@ -7453,6 +7500,8 @@ async function recall(query, ctx, options = {}) {
7453
7500
  hadV2Head = v2Head;
7454
7501
  if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
7455
7502
  factLaneRankedOnCosine = factRankedOnCosine;
7503
+ decryptLastRan = factDecryptLast;
7504
+ vaultRowsDecrypted = factRowsDecrypted;
7456
7505
  factLaneMs = nowMs() - factStart;
7457
7506
  }
7458
7507
  if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
@@ -7379,6 +7379,8 @@ async function recall(query, ctx, options = {}) {
7379
7379
  let embeddingsUnavailable = false;
7380
7380
  let chunkEmbedFailed = false;
7381
7381
  let factLaneRankedOnCosine = false;
7382
+ let decryptLastRan;
7383
+ let vaultRowsDecrypted;
7382
7384
  const emitDiagnostics = (candidateCount) => {
7383
7385
  const cb = options.onDiagnostics;
7384
7386
  if (!cb) return;
@@ -7395,6 +7397,8 @@ async function recall(query, ctx, options = {}) {
7395
7397
  reranked: didRerank,
7396
7398
  candidateCount,
7397
7399
  ...vaultSize !== void 0 && { vaultSize },
7400
+ ...decryptLastRan !== void 0 && { decryptLast: decryptLastRan },
7401
+ ...vaultRowsDecrypted !== void 0 && { vaultRowsDecrypted },
7398
7402
  factCount: factResults.length,
7399
7403
  chunkCount: chunkResults.length,
7400
7404
  timings: {
@@ -7466,7 +7470,9 @@ async function recall(query, ctx, options = {}) {
7466
7470
  reranked,
7467
7471
  hadV2Head: v2Head,
7468
7472
  embeddingsUnavailable: factEmbeddingsUnavailable,
7469
- rankedOnCosine: factRankedOnCosine
7473
+ rankedOnCosine: factRankedOnCosine,
7474
+ decryptLast: factDecryptLast,
7475
+ rowsDecrypted: factRowsDecrypted
7470
7476
  } = await searchVaultMemoriesWithSize(
7471
7477
  query,
7472
7478
  ctx.vaultCtx,
@@ -7523,6 +7529,8 @@ async function recall(query, ctx, options = {}) {
7523
7529
  hadV2Head = v2Head;
7524
7530
  if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
7525
7531
  factLaneRankedOnCosine = factRankedOnCosine;
7532
+ decryptLastRan = factDecryptLast;
7533
+ vaultRowsDecrypted = factRowsDecrypted;
7526
7534
  factLaneMs = nowMs() - factStart;
7527
7535
  }
7528
7536
  if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
@@ -8311,6 +8319,7 @@ function admitVaultProjections(queryEmbedding, vectored, k) {
8311
8319
  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);
8312
8320
  }
8313
8321
  async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, queryOpts, opts) {
8322
+ let rowsDecrypted = 0;
8314
8323
  const keys = await getVaultCandidateKeysOp(
8315
8324
  vaultCtx,
8316
8325
  Object.keys(queryOpts).length > 0 ? queryOpts : void 0
@@ -8323,7 +8332,8 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
8323
8332
  embeddedItems: [],
8324
8333
  queryEmbedding: [],
8325
8334
  vaultSize: 0,
8326
- laneEmbedFailed: false
8335
+ laneEmbedFailed: false,
8336
+ rowsDecrypted: 0
8327
8337
  };
8328
8338
  }
8329
8339
  const queryEmbedding = await embedQueryOrDegrade(
@@ -8369,6 +8379,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
8369
8379
  for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
8370
8380
  }
8371
8381
  let laneEmbedFailed = false;
8382
+ const laneById = /* @__PURE__ */ new Map();
8372
8383
  if (noVectorIds.length > 0) {
8373
8384
  const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
8374
8385
  if (noVectorIds.length > laneIds.length) {
@@ -8376,9 +8387,10 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
8376
8387
  `memoryVault: projected search un-embedded lane capped at ${laneIds.length}/${noVectorIds.length}`
8377
8388
  );
8378
8389
  }
8379
- const laneRows = (await getVaultMemoriesByIdsOp(vaultCtx, laneIds, hydrateOpts)).filter(
8380
- (m) => !isEncrypted(m.content)
8381
- );
8390
+ const laneFetched = await getVaultMemoriesByIdsOp(vaultCtx, laneIds, hydrateOpts);
8391
+ rowsDecrypted += laneFetched.length;
8392
+ for (const row of laneFetched) laneById.set(row.uniqueId, row);
8393
+ const laneRows = laneFetched.filter((m) => !isEncrypted(m.content));
8382
8394
  if (laneRows.length > 0) {
8383
8395
  let laneVecs;
8384
8396
  try {
@@ -8424,7 +8436,16 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
8424
8436
  if (keyById.has(id)) admissionSet.add(id);
8425
8437
  }
8426
8438
  }
8427
- const admittedRows = await getVaultMemoriesByIdsOp(vaultCtx, [...admissionSet], hydrateOpts);
8439
+ const idsToFetch = [...admissionSet].filter((id) => !laneById.has(id));
8440
+ const fetched = idsToFetch.length > 0 ? await getVaultMemoriesByIdsOp(vaultCtx, idsToFetch, hydrateOpts) : [];
8441
+ rowsDecrypted += fetched.length;
8442
+ const admittedRows = [
8443
+ ...fetched,
8444
+ ...[...admissionSet].flatMap((id) => {
8445
+ const reused = laneById.get(id);
8446
+ return reused ? [reused] : [];
8447
+ })
8448
+ ];
8428
8449
  const memories = admittedRows.filter((m) => !isEncrypted(m.content));
8429
8450
  if (memories.length < admittedRows.length) {
8430
8451
  getLogger().warn(
@@ -8445,7 +8466,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
8445
8466
  eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
8446
8467
  factType: m.factType
8447
8468
  }));
8448
- return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed };
8469
+ return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed, rowsDecrypted };
8449
8470
  }
8450
8471
  async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
8451
8472
  if (!query || typeof query !== "string") {
@@ -8455,7 +8476,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8455
8476
  queryEmbedding: [],
8456
8477
  vaultSize: 0,
8457
8478
  embeddingsUnavailable: false,
8458
- embeddingFailure: false
8479
+ embeddingFailure: false,
8480
+ decryptLast: !!searchOptions?.decryptLast,
8481
+ rowsDecrypted: 0
8459
8482
  };
8460
8483
  }
8461
8484
  const limit = searchOptions?.limit ?? 5;
@@ -8473,6 +8496,7 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8473
8496
  let embeddedItems;
8474
8497
  let queryEmbedding;
8475
8498
  let vaultSize;
8499
+ let rowsDecrypted;
8476
8500
  let embeddingsUnavailable = false;
8477
8501
  let embeddingFailure = false;
8478
8502
  const onEmbeddingDegraded = () => {
@@ -8499,10 +8523,13 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8499
8523
  queryEmbedding: [],
8500
8524
  vaultSize: 0,
8501
8525
  embeddingsUnavailable: false,
8502
- embeddingFailure: false
8526
+ embeddingFailure: false,
8527
+ decryptLast: true,
8528
+ rowsDecrypted: corpus.rowsDecrypted
8503
8529
  };
8504
8530
  }
8505
8531
  ({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
8532
+ rowsDecrypted = corpus.rowsDecrypted;
8506
8533
  if (corpus.laneEmbedFailed) embeddingFailure = true;
8507
8534
  if (memories.length === 0) {
8508
8535
  return {
@@ -8511,7 +8538,11 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8511
8538
  queryEmbedding: [],
8512
8539
  vaultSize,
8513
8540
  embeddingsUnavailable,
8514
- embeddingFailure
8541
+ embeddingFailure,
8542
+ decryptLast: true,
8543
+ // Rows WERE decrypt-attempted even though none came back readable — that
8544
+ // is the whole point of reporting attempts rather than successes.
8545
+ rowsDecrypted: corpus.rowsDecrypted
8515
8546
  };
8516
8547
  }
8517
8548
  } else {
@@ -8520,6 +8551,7 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8520
8551
  Object.keys(queryOpts).length > 0 ? queryOpts : void 0
8521
8552
  );
8522
8553
  vaultSize = loaded.length;
8554
+ rowsDecrypted = loaded.length;
8523
8555
  memories = loaded.filter((m) => !isEncrypted(m.content));
8524
8556
  if (memories.length < loaded.length) {
8525
8557
  getLogger().warn(
@@ -8533,7 +8565,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8533
8565
  queryEmbedding: [],
8534
8566
  vaultSize: loaded.length,
8535
8567
  embeddingsUnavailable: false,
8536
- embeddingFailure: false
8568
+ embeddingFailure: false,
8569
+ decryptLast: false,
8570
+ rowsDecrypted: loaded.length
8537
8571
  };
8538
8572
  }
8539
8573
  queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
@@ -8618,7 +8652,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
8618
8652
  queryEmbedding,
8619
8653
  vaultSize,
8620
8654
  embeddingsUnavailable,
8621
- embeddingFailure
8655
+ embeddingFailure,
8656
+ decryptLast: !!searchOptions?.decryptLast,
8657
+ rowsDecrypted
8622
8658
  };
8623
8659
  }
8624
8660
  async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
@@ -8786,7 +8822,11 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
8786
8822
  reranked: false,
8787
8823
  hadV2Head: false,
8788
8824
  embeddingsUnavailable: false,
8789
- rankedOnCosine: false
8825
+ rankedOnCosine: false,
8826
+ // No storage read happened, so nothing was decrypted; report the path the
8827
+ // caller asked for so this turn is still attributable.
8828
+ decryptLast: !!searchOptions?.decryptLast,
8829
+ rowsDecrypted: 0
8790
8830
  };
8791
8831
  }
8792
8832
  if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
@@ -8809,7 +8849,9 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
8809
8849
  reranked: false,
8810
8850
  hadV2Head: false,
8811
8851
  embeddingsUnavailable: prepared.embeddingsUnavailable,
8812
- rankedOnCosine: false
8852
+ rankedOnCosine: false,
8853
+ decryptLast: prepared.decryptLast,
8854
+ rowsDecrypted: prepared.rowsDecrypted
8813
8855
  };
8814
8856
  }
8815
8857
  if (prepared.memories.length === 0) {
@@ -8819,7 +8861,9 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
8819
8861
  reranked: false,
8820
8862
  hadV2Head: false,
8821
8863
  embeddingsUnavailable: prepared.embeddingsUnavailable,
8822
- rankedOnCosine: false
8864
+ rankedOnCosine: false,
8865
+ decryptLast: prepared.decryptLast,
8866
+ rowsDecrypted: prepared.rowsDecrypted
8823
8867
  };
8824
8868
  }
8825
8869
  const ranked = await rankPreparedVaultCandidates(
@@ -8828,7 +8872,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
8828
8872
  embeddingOptions,
8829
8873
  searchOptions
8830
8874
  );
8831
- return { ...ranked, rankedOnCosine: !ranked.embeddingsUnavailable };
8875
+ return {
8876
+ ...ranked,
8877
+ rankedOnCosine: !ranked.embeddingsUnavailable,
8878
+ decryptLast: prepared.decryptLast,
8879
+ rowsDecrypted: prepared.rowsDecrypted
8880
+ };
8832
8881
  }
8833
8882
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
8834
8883
  const { results } = await searchVaultMemoriesWithSize(
@@ -6779,6 +6779,27 @@ interface RecallDiagnostics {
6779
6779
  candidateCount: number;
6780
6780
  /** Total vault size when the fact lane ran (absent if it didn't). */
6781
6781
  vaultSize?: number;
6782
+ /**
6783
+ * Which vault read path the fact lane actually executed: `true` for the
6784
+ * projected key scan that decrypts only the admission window, `false` for the
6785
+ * legacy whole-vault load. Absent when the fact lane didn't run.
6786
+ *
6787
+ * Reported because "the option was passed" and "the branch ran" are different
6788
+ * facts, and #845 needed the second one: the projected path was enabled in
6789
+ * production and the p50 did not move, with no way to tell a flag that never
6790
+ * reached the bundle from a projection that isn't cheaper at that vault size.
6791
+ */
6792
+ decryptLast?: boolean;
6793
+ /**
6794
+ * Rows the fact lane paid to decrypt. Absent when it didn't run.
6795
+ *
6796
+ * Read against {@link RecallDiagnostics.vaultSize} — that ratio is the whole
6797
+ * point. `decryptLast` true with `vaultRowsDecrypted` ≈ `vaultSize` means the
6798
+ * admission window is admitting the entire vault and the projection is buying
6799
+ * nothing. Far below `vaultSize` with latency unchanged means the decrypt was
6800
+ * never the cost.
6801
+ */
6802
+ vaultRowsDecrypted?: number;
6782
6803
  /** Facts the fact lane returned (post-dedupe, pre-fusion). */
6783
6804
  factCount: number;
6784
6805
  /** Chunks the chunk lane returned (post-dedupe, pre-fusion). */
@@ -6779,6 +6779,27 @@ interface RecallDiagnostics {
6779
6779
  candidateCount: number;
6780
6780
  /** Total vault size when the fact lane ran (absent if it didn't). */
6781
6781
  vaultSize?: number;
6782
+ /**
6783
+ * Which vault read path the fact lane actually executed: `true` for the
6784
+ * projected key scan that decrypts only the admission window, `false` for the
6785
+ * legacy whole-vault load. Absent when the fact lane didn't run.
6786
+ *
6787
+ * Reported because "the option was passed" and "the branch ran" are different
6788
+ * facts, and #845 needed the second one: the projected path was enabled in
6789
+ * production and the p50 did not move, with no way to tell a flag that never
6790
+ * reached the bundle from a projection that isn't cheaper at that vault size.
6791
+ */
6792
+ decryptLast?: boolean;
6793
+ /**
6794
+ * Rows the fact lane paid to decrypt. Absent when it didn't run.
6795
+ *
6796
+ * Read against {@link RecallDiagnostics.vaultSize} — that ratio is the whole
6797
+ * point. `decryptLast` true with `vaultRowsDecrypted` ≈ `vaultSize` means the
6798
+ * admission window is admitting the entire vault and the projection is buying
6799
+ * nothing. Far below `vaultSize` with latency unchanged means the decrypt was
6800
+ * never the cost.
6801
+ */
6802
+ vaultRowsDecrypted?: number;
6782
6803
  /** Facts the fact lane returned (post-dedupe, pre-fusion). */
6783
6804
  factCount: number;
6784
6805
  /** Chunks the chunk lane returned (post-dedupe, pre-fusion). */
@@ -166,7 +166,7 @@ import {
166
166
  updateVaultMemoryOp,
167
167
  useEncryption,
168
168
  vaultMemoryToStored
169
- } from "./chunk-2V5CMLGK.mjs";
169
+ } from "./chunk-GIBV5GBW.mjs";
170
170
  import {
171
171
  PiiRedactor,
172
172
  createStreamingDeAnonymizer,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-2V5CMLGK.mjs";
3
+ } from "./chunk-GIBV5GBW.mjs";
4
4
  import "./chunk-ILAWDQDE.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {