@anuma/sdk 3.11.2 → 3.11.4

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.
@@ -5497,6 +5497,17 @@ var init_mmr = __esm({
5497
5497
  }
5498
5498
  });
5499
5499
 
5500
+ // src/lib/memory/recallConstants.ts
5501
+ var RECALL_TOOL_NAME, RECALL_MAX_LIMIT, EMBEDDINGS_DEGRADED_EMPTY;
5502
+ var init_recallConstants = __esm({
5503
+ "src/lib/memory/recallConstants.ts"() {
5504
+ "use strict";
5505
+ RECALL_TOOL_NAME = "recall_memory";
5506
+ RECALL_MAX_LIMIT = 50;
5507
+ EMBEDDINGS_DEGRADED_EMPTY = "Semantic memory search is temporarily unavailable, so only keyword matching ran and it found no matches. Do not conclude the user has no such memory \u2014 say the memory lookup was degraded, or retry with different keywords.";
5508
+ }
5509
+ });
5510
+
5500
5511
  // src/lib/memory/recency.ts
5501
5512
  function recencyMultiplier(updatedAt, opts = {}) {
5502
5513
  const noDate = opts.noDateMultiplier ?? DEFAULT_NO_DATE_MULTIPLIER;
@@ -6544,6 +6555,9 @@ async function recall(query, ctx, options = {}) {
6544
6555
  let vaultSize;
6545
6556
  let didRerank = false;
6546
6557
  let hadV2Head = false;
6558
+ let embeddingsUnavailable = false;
6559
+ let chunkEmbedFailed = false;
6560
+ let factLaneRankedOnCosine = false;
6547
6561
  const emitDiagnostics = (candidateCount) => {
6548
6562
  const cb = options.onDiagnostics;
6549
6563
  if (!cb) return;
@@ -6552,6 +6566,7 @@ async function recall(query, ctx, options = {}) {
6552
6566
  degraded.push("rerank-unavailable");
6553
6567
  }
6554
6568
  if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
6569
+ if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
6555
6570
  const diagnostics = {
6556
6571
  usedBudget,
6557
6572
  reranked: didRerank,
@@ -6582,7 +6597,26 @@ async function recall(query, ctx, options = {}) {
6582
6597
  const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
6583
6598
  const prepStart = nowMs();
6584
6599
  const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
6585
- needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
6600
+ // The chunk lane is cosine-only — `searchChunksOp` needs a real vector, and
6601
+ // there is no lexical fallback for it — so an embeddings outage must SKIP the
6602
+ // lane, not reject this shared Promise.all and take the primary fact lane
6603
+ // (which BM25 can still serve) down with it. Mirrors safeLane's posture.
6604
+ needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions).then((vec) => {
6605
+ if (vec.length === 0) {
6606
+ getLogger().warn(
6607
+ "[memory/recall] chunk-lane query embedding came back empty; skipping the chunk lane"
6608
+ );
6609
+ chunkEmbedFailed = true;
6610
+ return void 0;
6611
+ }
6612
+ return vec;
6613
+ }).catch((err) => {
6614
+ getLogger().warn(
6615
+ `[memory/recall] chunk-lane query embedding failed; skipping the chunk lane: ${err instanceof Error ? err.message : String(err)}`
6616
+ );
6617
+ chunkEmbedFailed = true;
6618
+ return void 0;
6619
+ }) : Promise.resolve(void 0),
6586
6620
  // The graph + temporal lanes are AUXILIARY (RRF side-signals). A transient
6587
6621
  // WatermelonDB throw in either must NOT reject this Promise.all and take
6588
6622
  // PRIMARY cosine/BM25 recall down with it — degrade the failing lane to an
@@ -6607,7 +6641,9 @@ async function recall(query, ctx, options = {}) {
6607
6641
  results,
6608
6642
  vaultSize: size,
6609
6643
  reranked,
6610
- hadV2Head: v2Head
6644
+ hadV2Head: v2Head,
6645
+ embeddingsUnavailable: factEmbeddingsUnavailable,
6646
+ rankedOnCosine: factRankedOnCosine
6611
6647
  } = await searchVaultMemoriesWithSize(
6612
6648
  query,
6613
6649
  ctx.vaultCtx,
@@ -6664,8 +6700,11 @@ async function recall(query, ctx, options = {}) {
6664
6700
  vaultSize = size;
6665
6701
  didRerank = reranked;
6666
6702
  hadV2Head = v2Head;
6703
+ if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
6704
+ factLaneRankedOnCosine = factRankedOnCosine;
6667
6705
  factLaneMs = nowMs() - factStart;
6668
6706
  }
6707
+ if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
6669
6708
  if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
6670
6709
  const chunkStart = nowMs();
6671
6710
  const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
@@ -7428,6 +7467,24 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
7428
7467
  );
7429
7468
  }
7430
7469
  }
7470
+ async function embedQueryOrDegrade(query, embeddingOptions, onDegraded) {
7471
+ try {
7472
+ const embedding = await generateEmbedding(query, embeddingOptions);
7473
+ if (embedding.length === 0) {
7474
+ getLogger().warn(
7475
+ "memoryVault: query embedding came back empty \u2014 falling back to BM25-only ranking for this search"
7476
+ );
7477
+ onDegraded?.();
7478
+ }
7479
+ return embedding;
7480
+ } catch (err) {
7481
+ getLogger().warn(
7482
+ "memoryVault: query embedding failed \u2014 falling back to BM25-only ranking for this search: " + (err instanceof Error ? err.message : String(err))
7483
+ );
7484
+ onDegraded?.();
7485
+ return [];
7486
+ }
7487
+ }
7431
7488
  function admitVaultProjections(queryEmbedding, vectored, k) {
7432
7489
  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);
7433
7490
  }
@@ -7439,23 +7496,36 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
7439
7496
  const hydrateOpts = queryOpts.includeArchived ? { includeArchived: true } : void 0;
7440
7497
  const vaultSize = keys.length;
7441
7498
  if (keys.length === 0) {
7442
- return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
7499
+ return {
7500
+ memories: [],
7501
+ embeddedItems: [],
7502
+ queryEmbedding: [],
7503
+ vaultSize: 0,
7504
+ laneEmbedFailed: false
7505
+ };
7443
7506
  }
7444
- const queryEmbedding = await generateEmbedding(query, embeddingOptions);
7507
+ const queryEmbedding = await embedQueryOrDegrade(
7508
+ query,
7509
+ embeddingOptions,
7510
+ opts.onEmbeddingDegraded
7511
+ );
7512
+ const embeddingsDegraded = queryEmbedding.length === 0;
7445
7513
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
7446
7514
  const vectored = [];
7447
7515
  const missIds = [];
7448
7516
  const noVectorIds = [];
7449
7517
  const keyById = new Map(keys.map((k2) => [k2.uniqueId, k2]));
7450
- for (const k2 of keys) {
7451
- const cached = cache.get(k2.uniqueId);
7452
- if (cached && cached.length === queryEmbedding.length) {
7453
- vectored.push({ uniqueId: k2.uniqueId, embedding: cached, updatedAt: k2.updatedAt });
7454
- continue;
7518
+ if (!embeddingsDegraded) {
7519
+ for (const k2 of keys) {
7520
+ const cached = cache.get(k2.uniqueId);
7521
+ if (cached && cached.length === queryEmbedding.length) {
7522
+ vectored.push({ uniqueId: k2.uniqueId, embedding: cached, updatedAt: k2.updatedAt });
7523
+ continue;
7524
+ }
7525
+ const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
7526
+ if (modelCompatible) missIds.push(k2.uniqueId);
7527
+ else noVectorIds.push(k2.uniqueId);
7455
7528
  }
7456
- const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
7457
- if (modelCompatible) missIds.push(k2.uniqueId);
7458
- else noVectorIds.push(k2.uniqueId);
7459
7529
  }
7460
7530
  if (missIds.length > 0) {
7461
7531
  const rows = await getVaultEmbeddingsByIdsOp(vaultCtx, missIds, hydrateOpts);
@@ -7476,6 +7546,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
7476
7546
  }
7477
7547
  for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
7478
7548
  }
7549
+ let laneEmbedFailed = false;
7479
7550
  if (noVectorIds.length > 0) {
7480
7551
  const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
7481
7552
  if (noVectorIds.length > laneIds.length) {
@@ -7487,26 +7558,44 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
7487
7558
  (m) => !isEncrypted(m.content)
7488
7559
  );
7489
7560
  if (laneRows.length > 0) {
7490
- const laneVecs = await generateEmbeddings(
7491
- laneRows.map((m) => m.content),
7492
- embeddingOptions
7493
- );
7494
- laneRows.forEach((m, i) => {
7495
- const vec = Float32Array.from(laneVecs[i]);
7496
- cache.set(m.uniqueId, vec);
7497
- vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
7498
- updateVaultMemoryEmbeddingOp(
7499
- vaultCtx,
7500
- m.uniqueId,
7501
- JSON.stringify(laneVecs[i]),
7502
- currentModel
7503
- ).catch(() => {
7561
+ let laneVecs;
7562
+ try {
7563
+ laneVecs = await generateEmbeddings(
7564
+ laneRows.map((m) => m.content),
7565
+ embeddingOptions
7566
+ );
7567
+ } catch (err) {
7568
+ laneEmbedFailed = true;
7569
+ getLogger().warn(
7570
+ `memoryVault: un-embedded lane embedding failed for ${laneRows.length} rows \u2014 they rank on BM25 alone for this search: ` + (err instanceof Error ? err.message : String(err))
7571
+ );
7572
+ }
7573
+ if (laneVecs) {
7574
+ const vecs = laneVecs;
7575
+ laneRows.forEach((m, i) => {
7576
+ const vec = Float32Array.from(vecs[i]);
7577
+ cache.set(m.uniqueId, vec);
7578
+ vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
7579
+ updateVaultMemoryEmbeddingOp(
7580
+ vaultCtx,
7581
+ m.uniqueId,
7582
+ JSON.stringify(vecs[i]),
7583
+ currentModel
7584
+ ).catch(() => {
7585
+ });
7504
7586
  });
7505
- });
7587
+ }
7506
7588
  }
7507
7589
  }
7508
7590
  const k = Math.max(opts.limit * opts.admitFactor, opts.admitFloor);
7509
7591
  const admittedIds = admitVaultProjections(queryEmbedding, vectored, k);
7592
+ if ((embeddingsDegraded || laneEmbedFailed) && admittedIds.length < k) {
7593
+ const already = new Set(admittedIds);
7594
+ for (const key of [...keys].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())) {
7595
+ if (admittedIds.length >= k) break;
7596
+ if (!already.has(key.uniqueId)) admittedIds.push(key.uniqueId);
7597
+ }
7598
+ }
7510
7599
  const admissionSet = new Set(admittedIds);
7511
7600
  if (opts.forceIncludeIds) {
7512
7601
  for (const id of opts.forceIncludeIds) {
@@ -7534,11 +7623,18 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
7534
7623
  eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
7535
7624
  factType: m.factType
7536
7625
  }));
7537
- return { memories, embeddedItems, queryEmbedding, vaultSize };
7626
+ return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed };
7538
7627
  }
7539
7628
  async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
7540
7629
  if (!query || typeof query !== "string") {
7541
- return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
7630
+ return {
7631
+ memories: [],
7632
+ embeddedItems: [],
7633
+ queryEmbedding: [],
7634
+ vaultSize: 0,
7635
+ embeddingsUnavailable: false,
7636
+ embeddingFailure: false
7637
+ };
7542
7638
  }
7543
7639
  const limit = searchOptions?.limit ?? 5;
7544
7640
  const scopes = searchOptions?.scopes;
@@ -7555,6 +7651,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
7555
7651
  let embeddedItems;
7556
7652
  let queryEmbedding;
7557
7653
  let vaultSize;
7654
+ let embeddingsUnavailable = false;
7655
+ let embeddingFailure = false;
7656
+ const onEmbeddingDegraded = () => {
7657
+ embeddingsUnavailable = true;
7658
+ embeddingFailure = true;
7659
+ };
7558
7660
  if (searchOptions?.decryptLast) {
7559
7661
  const forceIncludeIds = [
7560
7662
  ...searchOptions.entityRanking ?? [],
@@ -7565,14 +7667,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
7565
7667
  admitFactor: ADMIT_FACTOR,
7566
7668
  admitFloor: ADMIT_FLOOR,
7567
7669
  unembeddedCap: UNEMBEDDED_CAP,
7568
- ...forceIncludeIds.length > 0 && { forceIncludeIds }
7670
+ ...forceIncludeIds.length > 0 && { forceIncludeIds },
7671
+ onEmbeddingDegraded
7569
7672
  });
7570
7673
  if (corpus.vaultSize === 0) {
7571
- return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
7674
+ return {
7675
+ memories: [],
7676
+ embeddedItems: [],
7677
+ queryEmbedding: [],
7678
+ vaultSize: 0,
7679
+ embeddingsUnavailable: false,
7680
+ embeddingFailure: false
7681
+ };
7572
7682
  }
7573
7683
  ({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
7684
+ if (corpus.laneEmbedFailed) embeddingFailure = true;
7574
7685
  if (memories.length === 0) {
7575
- return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize };
7686
+ return {
7687
+ memories: [],
7688
+ embeddedItems: [],
7689
+ queryEmbedding: [],
7690
+ vaultSize,
7691
+ embeddingsUnavailable,
7692
+ embeddingFailure
7693
+ };
7576
7694
  }
7577
7695
  } else {
7578
7696
  const loaded = await getAllVaultMemoriesOp(
@@ -7587,14 +7705,21 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
7587
7705
  );
7588
7706
  }
7589
7707
  if (memories.length === 0) {
7590
- return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: loaded.length };
7708
+ return {
7709
+ memories: [],
7710
+ embeddedItems: [],
7711
+ queryEmbedding: [],
7712
+ vaultSize: loaded.length,
7713
+ embeddingsUnavailable: false,
7714
+ embeddingFailure: false
7715
+ };
7591
7716
  }
7592
- queryEmbedding = await generateEmbedding(query, embeddingOptions);
7717
+ queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
7593
7718
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
7594
7719
  const uncachedTexts = [];
7595
7720
  const uncachedIndices = [];
7596
7721
  let staleReembedCount = 0;
7597
- for (let i = 0; i < memories.length; i++) {
7722
+ for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
7598
7723
  const content = memories[i].content;
7599
7724
  const memoryId = memories[i].uniqueId;
7600
7725
  const cached = cache.get(memoryId);
@@ -7622,20 +7747,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
7622
7747
  );
7623
7748
  }
7624
7749
  if (uncachedTexts.length > 0) {
7625
- const newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
7626
- for (let j = 0; j < uncachedTexts.length; j++) {
7627
- cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
7628
- updateVaultMemoryEmbeddingOp(
7629
- vaultCtx,
7630
- memories[uncachedIndices[j]].uniqueId,
7631
- JSON.stringify(newEmbeddings[j]),
7632
- currentModel
7633
- ).catch(
7634
- // Silently swallow – SDK must not use console.*; embedding will be retried on next search
7635
- () => {
7636
- }
7750
+ let newEmbeddings;
7751
+ try {
7752
+ newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
7753
+ } catch (err) {
7754
+ embeddingFailure = true;
7755
+ getLogger().warn(
7756
+ `memoryVault: (re)embedding ${uncachedTexts.length} vault rows failed \u2014 they rank on BM25 alone for this search: ` + (err instanceof Error ? err.message : String(err))
7637
7757
  );
7638
7758
  }
7759
+ if (newEmbeddings) {
7760
+ for (let j = 0; j < uncachedTexts.length; j++) {
7761
+ cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
7762
+ updateVaultMemoryEmbeddingOp(
7763
+ vaultCtx,
7764
+ memories[uncachedIndices[j]].uniqueId,
7765
+ JSON.stringify(newEmbeddings[j]),
7766
+ currentModel
7767
+ ).catch(
7768
+ // Silently swallow – SDK must not use console.*; embedding will be retried on next search
7769
+ () => {
7770
+ }
7771
+ );
7772
+ }
7773
+ }
7639
7774
  }
7640
7775
  embeddedItems = memories.map((m) => ({
7641
7776
  id: m.uniqueId,
@@ -7652,12 +7787,22 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
7652
7787
  factType: m.factType
7653
7788
  }));
7654
7789
  }
7655
- return { memories, embeddedItems, queryEmbedding, vaultSize };
7790
+ if (!embeddingsUnavailable && !embeddedItems.some((it) => it.embedding.length > 0)) {
7791
+ embeddingsUnavailable = true;
7792
+ }
7793
+ return {
7794
+ memories,
7795
+ embeddedItems,
7796
+ queryEmbedding,
7797
+ vaultSize,
7798
+ embeddingsUnavailable,
7799
+ embeddingFailure
7800
+ };
7656
7801
  }
7657
7802
  async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
7658
7803
  const limit = searchOptions?.limit ?? 5;
7659
7804
  const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
7660
- const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
7805
+ const { memories, embeddedItems, queryEmbedding, vaultSize, embeddingsUnavailable } = prepared;
7661
7806
  if (queryEmbedding.length > 0) {
7662
7807
  const mismatched = embeddedItems.filter(
7663
7808
  (it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
@@ -7694,7 +7839,8 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
7694
7839
  results: results2,
7695
7840
  vaultSize: out.vaultSize,
7696
7841
  reranked: out.reranked ?? false,
7697
- hadV2Head: out.hadV2Head ?? false
7842
+ hadV2Head: out.hadV2Head ?? false,
7843
+ embeddingsUnavailable
7698
7844
  };
7699
7845
  };
7700
7846
  const rerankStats = { applied: false };
@@ -7717,36 +7863,46 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
7717
7863
  ...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
7718
7864
  ...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
7719
7865
  };
7720
- if (useFusion && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
7866
+ if (useFusion && !embeddingsUnavailable && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
7721
7867
  const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
7722
7868
  if (decomp.mode === "composite") {
7723
- const subEmbeddings = await generateEmbeddings(decomp.subQueries, embeddingOptions);
7724
- const subQueries = decomp.subQueries.map((sq, i) => ({
7725
- query: sq,
7726
- embedding: subEmbeddings[i]
7727
- }));
7728
- const v2HeadStats = { hadResults: false };
7729
- const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
7730
- limit,
7731
- minSimilarity,
7732
- rerank: !!searchOptions.rerank,
7733
- ...searchOptions.rerankTopN !== void 0 && {
7734
- rerankTopN: searchOptions.rerankTopN
7735
- },
7736
- ...searchOptions.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
7737
- ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
7738
- ...tuning,
7739
- ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
7740
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
7741
- rerankStats,
7742
- v2HeadStats
7743
- });
7744
- return stampTimestamps({
7745
- results: composite,
7746
- vaultSize,
7747
- reranked: rerankStats.applied,
7748
- hadV2Head: v2HeadStats.hadResults
7749
- });
7869
+ let subEmbeddings;
7870
+ try {
7871
+ subEmbeddings = await generateEmbeddings(decomp.subQueries, embeddingOptions);
7872
+ } catch (err) {
7873
+ getLogger().warn(
7874
+ "memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
7875
+ );
7876
+ subEmbeddings = [];
7877
+ }
7878
+ if (subEmbeddings.length > 0) {
7879
+ const subQueries = decomp.subQueries.map((sq, i) => ({
7880
+ query: sq,
7881
+ embedding: subEmbeddings[i]
7882
+ }));
7883
+ const v2HeadStats = { hadResults: false };
7884
+ const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
7885
+ limit,
7886
+ minSimilarity,
7887
+ rerank: !!searchOptions.rerank,
7888
+ ...searchOptions.rerankTopN !== void 0 && {
7889
+ rerankTopN: searchOptions.rerankTopN
7890
+ },
7891
+ ...searchOptions.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
7892
+ ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
7893
+ ...tuning,
7894
+ ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
7895
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
7896
+ rerankStats,
7897
+ v2HeadStats
7898
+ });
7899
+ return stampTimestamps({
7900
+ results: composite,
7901
+ vaultSize,
7902
+ reranked: rerankStats.applied,
7903
+ hadV2Head: v2HeadStats.hadResults
7904
+ });
7905
+ }
7750
7906
  }
7751
7907
  }
7752
7908
  if (useFusion && searchOptions?.rerank) {
@@ -7797,7 +7953,14 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
7797
7953
  }
7798
7954
  async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
7799
7955
  if (!query || typeof query !== "string") {
7800
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
7956
+ return {
7957
+ results: [],
7958
+ vaultSize: 0,
7959
+ reranked: false,
7960
+ hadV2Head: false,
7961
+ embeddingsUnavailable: false,
7962
+ rankedOnCosine: false
7963
+ };
7801
7964
  }
7802
7965
  const prepared = await prepareVaultCandidates(
7803
7966
  query,
@@ -7807,12 +7970,32 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
7807
7970
  searchOptions
7808
7971
  );
7809
7972
  if (prepared.vaultSize === 0) {
7810
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
7973
+ return {
7974
+ results: [],
7975
+ vaultSize: 0,
7976
+ reranked: false,
7977
+ hadV2Head: false,
7978
+ embeddingsUnavailable: prepared.embeddingsUnavailable,
7979
+ rankedOnCosine: false
7980
+ };
7811
7981
  }
7812
7982
  if (prepared.memories.length === 0) {
7813
- return { results: [], vaultSize: prepared.vaultSize, reranked: false, hadV2Head: false };
7983
+ return {
7984
+ results: [],
7985
+ vaultSize: prepared.vaultSize,
7986
+ reranked: false,
7987
+ hadV2Head: false,
7988
+ embeddingsUnavailable: prepared.embeddingsUnavailable,
7989
+ rankedOnCosine: false
7990
+ };
7814
7991
  }
7815
- return rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions);
7992
+ const ranked = await rankPreparedVaultCandidates(
7993
+ query,
7994
+ prepared,
7995
+ embeddingOptions,
7996
+ searchOptions
7997
+ );
7998
+ return { ...ranked, rankedOnCosine: !ranked.embeddingsUnavailable };
7816
7999
  }
7817
8000
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
7818
8001
  const { results } = await searchVaultMemoriesWithSize(
@@ -7886,26 +8069,36 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
7886
8069
  const budget = searchOptions?.decompose === "llm" && searchOptions.decomposeOptions ? "high" : searchOptions?.rerank ? "mid" : "low";
7887
8070
  const folderId = searchOptions?.folderId ?? argFolderId;
7888
8071
  if (searchOptions?.useFusion === false) {
7889
- const legacy = await searchVaultMemories(query, vaultCtx, embeddingOptions, cache, {
7890
- limit: requestLimit,
7891
- minSimilarity,
7892
- useFusion: false,
7893
- ...tuningForward,
7894
- ...folderId !== void 0 && { folderId },
7895
- ...searchOptions?.scopes && { scopes: searchOptions.scopes }
7896
- });
8072
+ const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
8073
+ query,
8074
+ vaultCtx,
8075
+ embeddingOptions,
8076
+ cache,
8077
+ {
8078
+ limit: requestLimit,
8079
+ minSimilarity,
8080
+ useFusion: false,
8081
+ ...tuningForward,
8082
+ ...folderId !== void 0 && { folderId },
8083
+ ...searchOptions?.scopes && { scopes: searchOptions.scopes }
8084
+ }
8085
+ );
7897
8086
  if (legacy.length === 0) {
7898
- return "No relevant memories found in the vault.";
8087
+ return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
7899
8088
  }
7900
8089
  return formatVaultHits(
7901
8090
  legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
7902
8091
  );
7903
8092
  }
7904
8093
  const { recall: recall2 } = await Promise.resolve().then(() => (init_recall(), recall_exports));
8094
+ let recallDegraded = [];
7905
8095
  const result = await recall2(
7906
8096
  query,
7907
8097
  { vaultCtx, embeddingOptions, vaultCache: cache },
7908
8098
  {
8099
+ onDiagnostics: (d) => {
8100
+ recallDegraded = d.degraded;
8101
+ },
7909
8102
  types: ["fact"],
7910
8103
  limit: requestLimit,
7911
8104
  minScore: minSimilarity,
@@ -7926,7 +8119,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
7926
8119
  return "The memory vault is empty. No memories have been saved yet.";
7927
8120
  }
7928
8121
  if (result.memories.length === 0) {
7929
- return "No relevant memories found in the vault.";
8122
+ return recallDegraded.includes("embeddings-unavailable") ? EMBEDDINGS_DEGRADED_EMPTY : "No relevant memories found in the vault.";
7930
8123
  }
7931
8124
  const formatted = formatVaultHits(
7932
8125
  result.memories.map((m) => ({
@@ -7945,7 +8138,7 @@ ${formatted}`;
7945
8138
  }
7946
8139
  };
7947
8140
  }
7948
- var SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW;
8141
+ var SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
7949
8142
  var init_searchTool = __esm({
7950
8143
  "src/lib/memoryVault/searchTool.ts"() {
7951
8144
  "use strict";
@@ -7953,6 +8146,7 @@ var init_searchTool = __esm({
7953
8146
  init_operations3();
7954
8147
  init_logger();
7955
8148
  init_mmr();
8149
+ init_recallConstants();
7956
8150
  init_recency();
7957
8151
  init_reranker();
7958
8152
  init_rrf();
@@ -7966,6 +8160,7 @@ var init_searchTool = __esm({
7966
8160
  SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
7967
8161
  SUPERSESSION_BOOST_FACTOR = 0.8;
7968
8162
  SUPERSESSION_MAX_WINDOW = 50;
8163
+ EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL = "Memory search is temporarily unavailable \u2014 the semantic lookup failed and this search mode has no keyword fallback, so no memory search ran at all. Do not conclude the user has no such memory; say the memory lookup was unavailable.";
7969
8164
  }
7970
8165
  });
7971
8166
 
@@ -14670,6 +14865,11 @@ async function retain(content, ctx, options = {}) {
14670
14865
  ...options.folderId !== void 0 && { folderId: options.folderId }
14671
14866
  }
14672
14867
  );
14868
+ if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
14869
+ throw new Error(
14870
+ "retain: embeddings unavailable \u2014 refusing to auto-merge against an inert cosine lane, which would create a duplicate instead of merging into the existing memory. Retry when embeddings recover, or pass enableAutoMerge: false to force a create."
14871
+ );
14872
+ }
14673
14873
  if (options.consolidateOptions) {
14674
14874
  const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
14675
14875
  if (outcome) {
@@ -15921,12 +16121,7 @@ init_recall();
15921
16121
 
15922
16122
  // src/lib/memory/recallTool.ts
15923
16123
  init_recall();
15924
-
15925
- // src/lib/memory/recallConstants.ts
15926
- var RECALL_TOOL_NAME = "recall_memory";
15927
- var RECALL_MAX_LIMIT = 50;
15928
-
15929
- // src/lib/memory/recallTool.ts
16124
+ init_recallConstants();
15930
16125
  var DEFAULT_LIMIT2 = 8;
15931
16126
  var DEFAULT_BUDGET2 = "low";
15932
16127
  function formatEventTime(start, end, kind) {
@@ -16076,7 +16271,11 @@ function createRecallTool(ctx, toolOptions, callbacks) {
16076
16271
  conversationMemories += effectiveLimit;
16077
16272
  let surfaced = 0;
16078
16273
  try {
16274
+ let recallDegraded = [];
16079
16275
  const recallOpts = {
16276
+ onDiagnostics: (d) => {
16277
+ recallDegraded = d.degraded;
16278
+ },
16080
16279
  types: defaultTypes,
16081
16280
  limit: effectiveLimit,
16082
16281
  budget: defaultBudget,
@@ -16108,6 +16307,9 @@ function createRecallTool(ctx, toolOptions, callbacks) {
16108
16307
  }
16109
16308
  }
16110
16309
  surfaced = result.memories.length;
16310
+ if (result.memories.length === 0 && recallDegraded.includes("embeddings-unavailable")) {
16311
+ return EMBEDDINGS_DEGRADED_EMPTY;
16312
+ }
16111
16313
  const formatted = formatRecallResult(result.memories);
16112
16314
  return truncatedByBudget && surfaced > 0 ? `${formatted}
16113
16315
 
@@ -16288,6 +16490,7 @@ init_embeddings();
16288
16490
  init_vector();
16289
16491
  init_observationTrend();
16290
16492
  init_recall();
16493
+ init_recallConstants();
16291
16494
  var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
16292
16495
  var DEFAULT_FACET_RECALL_LIMIT = 20;
16293
16496
  var DEFAULT_FACET_MAX_TOKENS = 512;
@@ -17210,6 +17413,7 @@ function createMemoryVaultTool(vaultCtx, options, embeddingOptions, cache) {
17210
17413
  init_redactor();
17211
17414
 
17212
17415
  // src/lib/tools/clientToolSelection.ts
17416
+ init_recallConstants();
17213
17417
  init_generate();
17214
17418
 
17215
17419
  // src/tools/appBuilderPrompt.ts