@anuma/sdk 4.2.1 → 5.0.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-3CDSIN22.mjs → chunk-SIMGZQ4P.mjs} +177 -148
- package/dist/expo/index.cjs +110 -71
- package/dist/expo/index.d.mts +69 -19
- package/dist/expo/index.d.ts +69 -19
- package/dist/expo/index.mjs +16 -6
- package/dist/expo/{recall-NARBDQAK.mjs → recall-PIDYDFIQ.mjs} +1 -1
- package/dist/react/{chunk-CUJDSH55.mjs → chunk-KTBOHRRE.mjs} +177 -148
- package/dist/react/index.cjs +110 -71
- package/dist/react/index.d.mts +69 -19
- package/dist/react/index.d.ts +69 -19
- package/dist/react/index.mjs +16 -6
- package/dist/react/{recall-FPPCKYYH.mjs → recall-DVX4W2UD.mjs} +1 -1
- package/dist/server/{chunk-UQDYBQVF.mjs → chunk-FKVYUOSD.mjs} +177 -148
- package/dist/server/index.cjs +110 -71
- package/dist/server/index.d.mts +69 -19
- package/dist/server/index.d.ts +69 -19
- package/dist/server/index.mjs +16 -6
- package/dist/server/{recall-ZHEPQNEU.mjs → recall-74L75BJ3.mjs} +1 -1
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -6684,11 +6684,11 @@ async function decomposeQuery(query, options) {
|
|
|
6684
6684
|
userMessage: `Classify the following memory query and decompose if composite. Respond with JSON only \u2014 do not answer the question, do not ask for clarification.
|
|
6685
6685
|
|
|
6686
6686
|
Query: ${trimmed}`,
|
|
6687
|
-
// Decompose runs
|
|
6687
|
+
// Decompose runs ahead of recall in the tool layer — tighter than the
|
|
6688
6688
|
// portalLlm default (consolidate/extract can wait longer).
|
|
6689
6689
|
timeoutMs: 2e4,
|
|
6690
6690
|
// No internal retry: a failure degrades to the safe `{specific,[query]}`
|
|
6691
|
-
// fallback below
|
|
6691
|
+
// fallback below. The agent/tool loop is the retry surface (719/B4).
|
|
6692
6692
|
maxAttempts: 1,
|
|
6693
6693
|
tag: "memory/decompose",
|
|
6694
6694
|
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
@@ -6700,12 +6700,28 @@ Query: ${trimmed}`,
|
|
|
6700
6700
|
if (parsed === null) return fallback;
|
|
6701
6701
|
return validate(parsed, trimmed) ?? fallback;
|
|
6702
6702
|
}
|
|
6703
|
+
function normalizeSubQueries(raw) {
|
|
6704
|
+
if (!raw || raw.length === 0) return [];
|
|
6705
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6706
|
+
const out = [];
|
|
6707
|
+
for (const s of raw) {
|
|
6708
|
+
if (typeof s !== "string") continue;
|
|
6709
|
+
const t = s.trim();
|
|
6710
|
+
if (t.length === 0) continue;
|
|
6711
|
+
const key = t.toLowerCase();
|
|
6712
|
+
if (seen.has(key)) continue;
|
|
6713
|
+
seen.add(key);
|
|
6714
|
+
out.push(t);
|
|
6715
|
+
if (out.length >= MAX_SUB_QUERIES) break;
|
|
6716
|
+
}
|
|
6717
|
+
return out;
|
|
6718
|
+
}
|
|
6703
6719
|
function validate(parsed, originalQuery) {
|
|
6704
6720
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
6705
6721
|
const obj = parsed;
|
|
6706
6722
|
const mode = obj.mode === "composite" ? "composite" : "specific";
|
|
6707
6723
|
if (!Array.isArray(obj.subQueries)) return null;
|
|
6708
|
-
const subQueries = obj.subQueries
|
|
6724
|
+
const subQueries = normalizeSubQueries(obj.subQueries);
|
|
6709
6725
|
if (subQueries.length === 0) return null;
|
|
6710
6726
|
if (mode === "specific") {
|
|
6711
6727
|
return { mode: "specific", subQueries: [originalQuery] };
|
|
@@ -7322,12 +7338,12 @@ __export(recall_exports, {
|
|
|
7322
7338
|
function flagsForBudget(budget) {
|
|
7323
7339
|
switch (budget) {
|
|
7324
7340
|
case "high":
|
|
7325
|
-
return { rerank: true,
|
|
7341
|
+
return { rerank: true, traverse: true };
|
|
7326
7342
|
case "mid":
|
|
7327
|
-
return { rerank: true,
|
|
7343
|
+
return { rerank: true, traverse: false };
|
|
7328
7344
|
case "low":
|
|
7329
7345
|
default:
|
|
7330
|
-
return { rerank: false,
|
|
7346
|
+
return { rerank: false, traverse: false };
|
|
7331
7347
|
}
|
|
7332
7348
|
}
|
|
7333
7349
|
function dedupeBy(items, ...keys) {
|
|
@@ -7346,10 +7362,10 @@ function dedupeBy(items, ...keys) {
|
|
|
7346
7362
|
async function recall(query, ctx, options = {}) {
|
|
7347
7363
|
const types = options.types ?? ["fact"];
|
|
7348
7364
|
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
7349
|
-
const
|
|
7350
|
-
const flags = flagsForBudget(
|
|
7351
|
-
const
|
|
7352
|
-
const
|
|
7365
|
+
const usedBudget = options.budget ?? DEFAULT_BUDGET;
|
|
7366
|
+
const flags = flagsForBudget(usedBudget);
|
|
7367
|
+
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
7368
|
+
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
7353
7369
|
const t0 = nowMs();
|
|
7354
7370
|
let prepMs = 0;
|
|
7355
7371
|
let factLaneMs = 0;
|
|
@@ -7370,7 +7386,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
7370
7386
|
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
7371
7387
|
degraded.push("rerank-unavailable");
|
|
7372
7388
|
}
|
|
7373
|
-
if (
|
|
7389
|
+
if (usedBudget === "high" && options.decomposeOptions && !subQueries && !options.graphRefine) {
|
|
7390
|
+
degraded.push("decompose-moved");
|
|
7391
|
+
}
|
|
7374
7392
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
7375
7393
|
const diagnostics = {
|
|
7376
7394
|
usedBudget,
|
|
@@ -7483,10 +7501,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
7483
7501
|
},
|
|
7484
7502
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
7485
7503
|
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
decomposeOptions: options.decomposeOptions
|
|
7489
|
-
},
|
|
7504
|
+
// 719/B4 — composite facets arrive pre-built; no LLM call here.
|
|
7505
|
+
...subQueries && { subQueries },
|
|
7490
7506
|
...options.scopes && { scopes: options.scopes },
|
|
7491
7507
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
7492
7508
|
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
@@ -7723,6 +7739,7 @@ var init_recall = __esm({
|
|
|
7723
7739
|
init_logger();
|
|
7724
7740
|
init_constants();
|
|
7725
7741
|
init_embeddings();
|
|
7742
|
+
init_decomposeQuery();
|
|
7726
7743
|
init_searchTool();
|
|
7727
7744
|
init_graphTraversal();
|
|
7728
7745
|
init_observationTrend();
|
|
@@ -8668,52 +8685,51 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
8668
8685
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
8669
8686
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
8670
8687
|
};
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
}
|
|
8688
|
+
const normalizedFacets = normalizeSubQueries(searchOptions?.subQueries);
|
|
8689
|
+
const facetQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
8690
|
+
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
8691
|
+
let subEmbeddings;
|
|
8692
|
+
try {
|
|
8693
|
+
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
8694
|
+
} catch (err) {
|
|
8695
|
+
getLogger().warn(
|
|
8696
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
8697
|
+
);
|
|
8698
|
+
subEmbeddings = [];
|
|
8699
|
+
}
|
|
8700
|
+
const subEmbeddingsUsable = facetQueries.length > 0 && subEmbeddings.length === facetQueries.length && subEmbeddings.every((v) => v.length > 0 && v.length === queryEmbedding.length);
|
|
8701
|
+
if (subEmbeddings.length > 0 && !subEmbeddingsUsable) {
|
|
8702
|
+
getLogger().warn(
|
|
8703
|
+
`memoryVault: sub-query embedding returned ${subEmbeddings.length} vectors (dims ${subEmbeddings.map((v) => v.length).join(",")}) for ${facetQueries.length} sub-queries against a ${queryEmbedding.length}-dim query \u2014 falling back to single-query ranking`
|
|
8704
|
+
);
|
|
8705
|
+
}
|
|
8706
|
+
if (subEmbeddingsUsable) {
|
|
8707
|
+
const subQueries = facetQueries.map((sq, i) => ({
|
|
8708
|
+
query: sq,
|
|
8709
|
+
embedding: subEmbeddings[i]
|
|
8710
|
+
}));
|
|
8711
|
+
const v2HeadStats = { hadResults: false };
|
|
8712
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
8713
|
+
limit,
|
|
8714
|
+
minSimilarity,
|
|
8715
|
+
rerank: !!searchOptions?.rerank,
|
|
8716
|
+
...searchOptions?.rerankTopN !== void 0 && {
|
|
8717
|
+
rerankTopN: searchOptions.rerankTopN
|
|
8718
|
+
},
|
|
8719
|
+
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
8720
|
+
...searchOptions?.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
8721
|
+
...tuning,
|
|
8722
|
+
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
8723
|
+
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
8724
|
+
rerankStats,
|
|
8725
|
+
v2HeadStats
|
|
8726
|
+
});
|
|
8727
|
+
return stampTimestamps({
|
|
8728
|
+
results: composite,
|
|
8729
|
+
vaultSize,
|
|
8730
|
+
reranked: rerankStats.applied,
|
|
8731
|
+
hadV2Head: v2HeadStats.hadResults
|
|
8732
|
+
});
|
|
8717
8733
|
}
|
|
8718
8734
|
}
|
|
8719
8735
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -8773,6 +8789,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
8773
8789
|
rankedOnCosine: false
|
|
8774
8790
|
};
|
|
8775
8791
|
}
|
|
8792
|
+
if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
|
|
8793
|
+
warnedProgrammaticDecomposeIgnored = true;
|
|
8794
|
+
getLogger().warn(
|
|
8795
|
+
'memoryVault: decompose:"llm" is ignored by searchVaultMemories \u2014 pass subQueries or use createMemoryVaultSearchTool / createRecallTool (719/B4)'
|
|
8796
|
+
);
|
|
8797
|
+
}
|
|
8776
8798
|
const prepared = await prepareVaultCandidates(
|
|
8777
8799
|
query,
|
|
8778
8800
|
vaultCtx,
|
|
@@ -8877,7 +8899,8 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8877
8899
|
return "Error: A search query is required.";
|
|
8878
8900
|
}
|
|
8879
8901
|
try {
|
|
8880
|
-
const
|
|
8902
|
+
const wantsDecompose = searchOptions?.decompose === "llm" && !!searchOptions.decomposeOptions;
|
|
8903
|
+
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
8881
8904
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
8882
8905
|
if (searchOptions?.useFusion === false) {
|
|
8883
8906
|
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
@@ -8901,6 +8924,13 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8901
8924
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
8902
8925
|
);
|
|
8903
8926
|
}
|
|
8927
|
+
let subQueries;
|
|
8928
|
+
if (wantsDecompose && searchOptions?.decomposeOptions) {
|
|
8929
|
+
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
8930
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
8931
|
+
subQueries = decomp.subQueries;
|
|
8932
|
+
}
|
|
8933
|
+
}
|
|
8904
8934
|
const { recall: recall2 } = await Promise.resolve().then(() => (init_recall(), recall_exports));
|
|
8905
8935
|
let recallDegraded = [];
|
|
8906
8936
|
const result = await recall2(
|
|
@@ -8917,9 +8947,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8917
8947
|
...tuningForward,
|
|
8918
8948
|
...folderId !== void 0 && { folderId },
|
|
8919
8949
|
...searchOptions?.scopes && { scopes: searchOptions.scopes },
|
|
8920
|
-
...
|
|
8921
|
-
decomposeOptions: searchOptions.decomposeOptions
|
|
8922
|
-
}
|
|
8950
|
+
...subQueries && { subQueries }
|
|
8923
8951
|
}
|
|
8924
8952
|
);
|
|
8925
8953
|
if (result.vaultSize === 0) {
|
|
@@ -8949,7 +8977,7 @@ ${formatted}`;
|
|
|
8949
8977
|
}
|
|
8950
8978
|
};
|
|
8951
8979
|
}
|
|
8952
|
-
var SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
8980
|
+
var warnedProgrammaticDecomposeIgnored, SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
8953
8981
|
var init_searchTool = __esm({
|
|
8954
8982
|
"src/lib/memoryVault/searchTool.ts"() {
|
|
8955
8983
|
"use strict";
|
|
@@ -8967,6 +8995,7 @@ var init_searchTool = __esm({
|
|
|
8967
8995
|
init_bm25();
|
|
8968
8996
|
init_decomposeQuery();
|
|
8969
8997
|
init_lruCache();
|
|
8998
|
+
warnedProgrammaticDecomposeIgnored = false;
|
|
8970
8999
|
SUPERSESSION_SIMILARITY_THRESHOLD = 0.7;
|
|
8971
9000
|
SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
8972
9001
|
SUPERSESSION_BOOST_FACTOR = 0.8;
|
|
@@ -18014,6 +18043,7 @@ function rankProfileCandidates(inputs, now = Date.now(), options = {}) {
|
|
|
18014
18043
|
init_recall();
|
|
18015
18044
|
|
|
18016
18045
|
// src/lib/memory/recallTool.ts
|
|
18046
|
+
init_decomposeQuery();
|
|
18017
18047
|
init_recall();
|
|
18018
18048
|
init_recallConstants();
|
|
18019
18049
|
var DEFAULT_LIMIT2 = 8;
|
|
@@ -18111,7 +18141,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
18111
18141
|
type: "function",
|
|
18112
18142
|
function: {
|
|
18113
18143
|
name: RECALL_TOOL_NAME,
|
|
18114
|
-
description:
|
|
18144
|
+
description: `Search the user's memory across stored facts/preferences and past conversation excerpts. Returns a unified ranked list \u2014 facts carry an \`id\` you can reference; conversation excerpts carry a date and role. Use this whenever the user's question may relate to anything previously discussed or saved (preferences, prior decisions, past topics). Phrase the query naturally. For multi-faceted / overview questions ("tell me about the user", "what's my tech stack"), prefer several targeted searches \u2014 one facet each (e.g. name, work, hobbies) \u2014 over a single broad query; fuse the results yourself.`,
|
|
18115
18145
|
arguments: {
|
|
18116
18146
|
type: "object",
|
|
18117
18147
|
properties: {
|
|
@@ -18166,6 +18196,13 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
18166
18196
|
let surfaced = 0;
|
|
18167
18197
|
try {
|
|
18168
18198
|
let recallDegraded = [];
|
|
18199
|
+
let subQueries;
|
|
18200
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
18201
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
18202
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
18203
|
+
subQueries = decomp.subQueries;
|
|
18204
|
+
}
|
|
18205
|
+
}
|
|
18169
18206
|
const recallOpts = {
|
|
18170
18207
|
onDiagnostics: (d) => {
|
|
18171
18208
|
recallDegraded = d.degraded;
|
|
@@ -18179,10 +18216,12 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
18179
18216
|
...toolOptions?.excludeConversationId && {
|
|
18180
18217
|
excludeConversationId: toolOptions.excludeConversationId
|
|
18181
18218
|
},
|
|
18182
|
-
|
|
18183
|
-
|
|
18184
|
-
|
|
18185
|
-
|
|
18219
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
18220
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
18221
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
18222
|
+
// be threaded later when the tool opts into that path.
|
|
18223
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
18224
|
+
...subQueries && { subQueries }
|
|
18186
18225
|
};
|
|
18187
18226
|
const result = await recall(query, ctx, recallOpts);
|
|
18188
18227
|
if (callbacks?.onChunksRetrieved) {
|
package/dist/react/index.d.mts
CHANGED
|
@@ -6282,15 +6282,26 @@ interface MemoryVaultSearchOptions {
|
|
|
6282
6282
|
/** RRF smoothing constant for lane fusion. Default 60. */
|
|
6283
6283
|
rrfK?: number;
|
|
6284
6284
|
/**
|
|
6285
|
-
*
|
|
6286
|
-
*
|
|
6287
|
-
*
|
|
6288
|
-
*
|
|
6285
|
+
* Pre-decomposed facet queries for the composite ranker (719/B4). When
|
|
6286
|
+
* ≥2 are supplied (and embeddings are available), runs {@link rankComposite}
|
|
6287
|
+
* over them — no LLM call inside the search path. Callers that want LLM
|
|
6288
|
+
* rewrite (e.g. `createRecallTool`) call `decomposeQuery` first and pass
|
|
6289
|
+
* the facets here.
|
|
6290
|
+
*/
|
|
6291
|
+
subQueries?: string[];
|
|
6292
|
+
/**
|
|
6293
|
+
* @deprecated 719/B4 — ignored by {@link searchVaultMemories} /
|
|
6294
|
+
* {@link searchVaultMemoriesWithSize}. Pass {@link MemoryVaultSearchOptions.subQueries}
|
|
6295
|
+
* (or use `createRecallTool`). The legacy {@link createMemoryVaultSearchTool}
|
|
6296
|
+
* executor still honors `decompose: "llm"` + `decomposeOptions` for eval
|
|
6297
|
+
* parity, then forwards facets into the LLM-free search path.
|
|
6289
6298
|
*/
|
|
6290
6299
|
decompose?: "off" | "llm";
|
|
6291
|
-
/**
|
|
6292
|
-
*
|
|
6293
|
-
*
|
|
6300
|
+
/**
|
|
6301
|
+
* @deprecated 719/B4 — see `decompose`. Ignored on the programmatic search
|
|
6302
|
+
* path; tool-layer rewrite still reads this from the search-tool options.
|
|
6303
|
+
* Prefer `RecallToolOptions.decomposeOptions` with `createRecallTool`.
|
|
6304
|
+
*/
|
|
6294
6305
|
decomposeOptions?: PortalLlmAuth & {
|
|
6295
6306
|
baseUrl?: string;
|
|
6296
6307
|
model?: string;
|
|
@@ -6455,9 +6466,11 @@ type MemoryKind = "fact" | "chunk";
|
|
|
6455
6466
|
* Budget controls retrieval depth/cost. Higher budgets enable more
|
|
6456
6467
|
* candidate sources and the cross-encoder reranker.
|
|
6457
6468
|
*
|
|
6458
|
-
* - `low`: cosine + BM25
|
|
6459
|
-
* - `mid`: +
|
|
6460
|
-
* - `high`: +
|
|
6469
|
+
* - `low`: cosine + BM25 + recency. No reranker. Mobile default.
|
|
6470
|
+
* - `mid`: + cross-encoder rerank.
|
|
6471
|
+
* - `high`: + multi-hop graph traversal. LLM-free — query decomposition
|
|
6472
|
+
* (when wanted) lives in the tool/agent layer ({@link createRecallTool}),
|
|
6473
|
+
* not inside `recall()` itself (719/B4).
|
|
6461
6474
|
*/
|
|
6462
6475
|
type Budget = "low" | "mid" | "high";
|
|
6463
6476
|
interface ScoreBreakdown {
|
|
@@ -6557,10 +6570,28 @@ interface RecallOptions {
|
|
|
6557
6570
|
/** Drop results below this score. Default: 0.1 for facts, 0.5 for chunks (mirrors today's defaults). */
|
|
6558
6571
|
minScore?: number;
|
|
6559
6572
|
/**
|
|
6560
|
-
*
|
|
6561
|
-
*
|
|
6562
|
-
*
|
|
6563
|
-
*
|
|
6573
|
+
* Pre-decomposed facet queries for the composite ranker. When ≥2 are
|
|
6574
|
+
* supplied, the vault lane runs `rankComposite` over them (no LLM call
|
|
6575
|
+
* inside `recall()` — 719/B4). Callers that still want LLM rewrite
|
|
6576
|
+
* (e.g. {@link createRecallTool} at `budget: 'high'`) call
|
|
6577
|
+
* `decomposeQuery` themselves and pass the result here. A single entry
|
|
6578
|
+
* (or omitting this) keeps the single-query path.
|
|
6579
|
+
*/
|
|
6580
|
+
subQueries?: string[];
|
|
6581
|
+
/**
|
|
6582
|
+
* Auth + endpoint for optional LLM helpers that reuse portal auth —
|
|
6583
|
+
* currently {@link RecallOptions.graphRefine} neighbor selection.
|
|
6584
|
+
* Query decomposition is **not** driven by this field inside `recall()`
|
|
6585
|
+
* (719/B4); {@link createRecallTool} reads the same shape from
|
|
6586
|
+
* `RecallToolOptions.decomposeOptions` for tool-layer rewrite.
|
|
6587
|
+
*
|
|
6588
|
+
* Callers that still pass `{ budget: 'high', decomposeOptions }` without
|
|
6589
|
+
* {@link RecallOptions.subQueries} keep compiling but no longer rewrite —
|
|
6590
|
+
* `recall()` emits `decompose-moved` on {@link RecallDiagnostics.degraded}
|
|
6591
|
+
* so upgrades without a changelog read still leave a telemetry breadcrumb.
|
|
6592
|
+
*
|
|
6593
|
+
* Auth is the dual pattern — one of `apiKey` / `getToken` is required;
|
|
6594
|
+
* see {@link PortalLlmAuth}.
|
|
6564
6595
|
*/
|
|
6565
6596
|
decomposeOptions?: PortalLlmAuth & {
|
|
6566
6597
|
baseUrl?: string;
|
|
@@ -6664,9 +6695,22 @@ type RecallDegradation =
|
|
|
6664
6695
|
/** Rerank was requested (budget mid/high) but the cross-encoder didn't run
|
|
6665
6696
|
* this call — unavailable (e.g. React Native) or a transient failure. */
|
|
6666
6697
|
"rerank-unavailable"
|
|
6667
|
-
/**
|
|
6668
|
-
*
|
|
6698
|
+
/**
|
|
6699
|
+
* @deprecated 719/B4 moved query decomposition out of `recall()`. Budget
|
|
6700
|
+
* `high` no longer requires `decomposeOptions` and this signal is never
|
|
6701
|
+
* emitted. Prefer `"decompose-moved"` for the upgrade breadcrumb. Kept in
|
|
6702
|
+
* the union so existing telemetry consumers stay typed.
|
|
6703
|
+
*/
|
|
6669
6704
|
| "decompose-unavailable"
|
|
6705
|
+
/**
|
|
6706
|
+
* `budget: 'high'` with `decomposeOptions` set but no usable
|
|
6707
|
+
* {@link RecallOptions.subQueries}. Pre-B4 this call shape triggered LLM
|
|
6708
|
+
* rewrite inside `recall()`; post-B4 it stays on the single-query high
|
|
6709
|
+
* path (rerank + graph) and callers must pass facets (or use
|
|
6710
|
+
* {@link createRecallTool}). Surfaced so silent quality regressions show
|
|
6711
|
+
* up in diagnostics instead of looking healthier than before.
|
|
6712
|
+
*/
|
|
6713
|
+
| "decompose-moved"
|
|
6670
6714
|
/** There was no usable cosine lane, so results were ranked on BM25 (lexical)
|
|
6671
6715
|
* alone: either the query embedding failed (or came back empty), or no
|
|
6672
6716
|
* candidate had a vector to score against it because the row (re)embed failed.
|
|
@@ -8706,9 +8750,14 @@ declare function rankProfileCandidates(inputs: readonly ProfileSalienceInput[],
|
|
|
8706
8750
|
* Unified Recall API — single retrieval surface above vault + engine.
|
|
8707
8751
|
*
|
|
8708
8752
|
* Budget maps to pipeline depth (mirrors Hindsight's tiered defaults):
|
|
8709
|
-
* - `low` → V2 cosine + BM25 + recency (no rerank
|
|
8753
|
+
* - `low` → V2 cosine + BM25 + recency (no rerank)
|
|
8710
8754
|
* - `mid` → V2 + cross-encoder rerank
|
|
8711
|
-
* - `high` → V2 + rerank +
|
|
8755
|
+
* - `high` → V2 + rerank + multi-hop graph traversal
|
|
8756
|
+
*
|
|
8757
|
+
* LLM-free by design (719/B4): query decomposition for composite asks
|
|
8758
|
+
* lives in the tool/agent layer (`createRecallTool`), which may pass
|
|
8759
|
+
* pre-built `subQueries` into this API. `recall()` itself never pays an
|
|
8760
|
+
* LLM RTT.
|
|
8712
8761
|
*
|
|
8713
8762
|
* Fact + chunk lanes are fused with RRF (k=60). The previous naive
|
|
8714
8763
|
* "sort the union by raw score" path is gone — score scales differ
|
|
@@ -8763,7 +8812,8 @@ interface RecallToolOptions {
|
|
|
8763
8812
|
folderId?: string | null;
|
|
8764
8813
|
/** Exclude one conversation from chunk results (typically the active one). */
|
|
8765
8814
|
excludeConversationId?: string;
|
|
8766
|
-
/** LLM-decompose options; only used at budget="high".
|
|
8815
|
+
/** LLM-decompose options; only used at budget="high". Runs in THIS tool
|
|
8816
|
+
* executor (719/B4) — `recall()` itself is LLM-free. Auth follows the
|
|
8767
8817
|
* dual pattern: apiKey (server/CLI) or getToken (browser identity
|
|
8768
8818
|
* tokens) — at least one required. */
|
|
8769
8819
|
decomposeOptions?: PortalLlmAuth & {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -6282,15 +6282,26 @@ interface MemoryVaultSearchOptions {
|
|
|
6282
6282
|
/** RRF smoothing constant for lane fusion. Default 60. */
|
|
6283
6283
|
rrfK?: number;
|
|
6284
6284
|
/**
|
|
6285
|
-
*
|
|
6286
|
-
*
|
|
6287
|
-
*
|
|
6288
|
-
*
|
|
6285
|
+
* Pre-decomposed facet queries for the composite ranker (719/B4). When
|
|
6286
|
+
* ≥2 are supplied (and embeddings are available), runs {@link rankComposite}
|
|
6287
|
+
* over them — no LLM call inside the search path. Callers that want LLM
|
|
6288
|
+
* rewrite (e.g. `createRecallTool`) call `decomposeQuery` first and pass
|
|
6289
|
+
* the facets here.
|
|
6290
|
+
*/
|
|
6291
|
+
subQueries?: string[];
|
|
6292
|
+
/**
|
|
6293
|
+
* @deprecated 719/B4 — ignored by {@link searchVaultMemories} /
|
|
6294
|
+
* {@link searchVaultMemoriesWithSize}. Pass {@link MemoryVaultSearchOptions.subQueries}
|
|
6295
|
+
* (or use `createRecallTool`). The legacy {@link createMemoryVaultSearchTool}
|
|
6296
|
+
* executor still honors `decompose: "llm"` + `decomposeOptions` for eval
|
|
6297
|
+
* parity, then forwards facets into the LLM-free search path.
|
|
6289
6298
|
*/
|
|
6290
6299
|
decompose?: "off" | "llm";
|
|
6291
|
-
/**
|
|
6292
|
-
*
|
|
6293
|
-
*
|
|
6300
|
+
/**
|
|
6301
|
+
* @deprecated 719/B4 — see `decompose`. Ignored on the programmatic search
|
|
6302
|
+
* path; tool-layer rewrite still reads this from the search-tool options.
|
|
6303
|
+
* Prefer `RecallToolOptions.decomposeOptions` with `createRecallTool`.
|
|
6304
|
+
*/
|
|
6294
6305
|
decomposeOptions?: PortalLlmAuth & {
|
|
6295
6306
|
baseUrl?: string;
|
|
6296
6307
|
model?: string;
|
|
@@ -6455,9 +6466,11 @@ type MemoryKind = "fact" | "chunk";
|
|
|
6455
6466
|
* Budget controls retrieval depth/cost. Higher budgets enable more
|
|
6456
6467
|
* candidate sources and the cross-encoder reranker.
|
|
6457
6468
|
*
|
|
6458
|
-
* - `low`: cosine + BM25
|
|
6459
|
-
* - `mid`: +
|
|
6460
|
-
* - `high`: +
|
|
6469
|
+
* - `low`: cosine + BM25 + recency. No reranker. Mobile default.
|
|
6470
|
+
* - `mid`: + cross-encoder rerank.
|
|
6471
|
+
* - `high`: + multi-hop graph traversal. LLM-free — query decomposition
|
|
6472
|
+
* (when wanted) lives in the tool/agent layer ({@link createRecallTool}),
|
|
6473
|
+
* not inside `recall()` itself (719/B4).
|
|
6461
6474
|
*/
|
|
6462
6475
|
type Budget = "low" | "mid" | "high";
|
|
6463
6476
|
interface ScoreBreakdown {
|
|
@@ -6557,10 +6570,28 @@ interface RecallOptions {
|
|
|
6557
6570
|
/** Drop results below this score. Default: 0.1 for facts, 0.5 for chunks (mirrors today's defaults). */
|
|
6558
6571
|
minScore?: number;
|
|
6559
6572
|
/**
|
|
6560
|
-
*
|
|
6561
|
-
*
|
|
6562
|
-
*
|
|
6563
|
-
*
|
|
6573
|
+
* Pre-decomposed facet queries for the composite ranker. When ≥2 are
|
|
6574
|
+
* supplied, the vault lane runs `rankComposite` over them (no LLM call
|
|
6575
|
+
* inside `recall()` — 719/B4). Callers that still want LLM rewrite
|
|
6576
|
+
* (e.g. {@link createRecallTool} at `budget: 'high'`) call
|
|
6577
|
+
* `decomposeQuery` themselves and pass the result here. A single entry
|
|
6578
|
+
* (or omitting this) keeps the single-query path.
|
|
6579
|
+
*/
|
|
6580
|
+
subQueries?: string[];
|
|
6581
|
+
/**
|
|
6582
|
+
* Auth + endpoint for optional LLM helpers that reuse portal auth —
|
|
6583
|
+
* currently {@link RecallOptions.graphRefine} neighbor selection.
|
|
6584
|
+
* Query decomposition is **not** driven by this field inside `recall()`
|
|
6585
|
+
* (719/B4); {@link createRecallTool} reads the same shape from
|
|
6586
|
+
* `RecallToolOptions.decomposeOptions` for tool-layer rewrite.
|
|
6587
|
+
*
|
|
6588
|
+
* Callers that still pass `{ budget: 'high', decomposeOptions }` without
|
|
6589
|
+
* {@link RecallOptions.subQueries} keep compiling but no longer rewrite —
|
|
6590
|
+
* `recall()` emits `decompose-moved` on {@link RecallDiagnostics.degraded}
|
|
6591
|
+
* so upgrades without a changelog read still leave a telemetry breadcrumb.
|
|
6592
|
+
*
|
|
6593
|
+
* Auth is the dual pattern — one of `apiKey` / `getToken` is required;
|
|
6594
|
+
* see {@link PortalLlmAuth}.
|
|
6564
6595
|
*/
|
|
6565
6596
|
decomposeOptions?: PortalLlmAuth & {
|
|
6566
6597
|
baseUrl?: string;
|
|
@@ -6664,9 +6695,22 @@ type RecallDegradation =
|
|
|
6664
6695
|
/** Rerank was requested (budget mid/high) but the cross-encoder didn't run
|
|
6665
6696
|
* this call — unavailable (e.g. React Native) or a transient failure. */
|
|
6666
6697
|
"rerank-unavailable"
|
|
6667
|
-
/**
|
|
6668
|
-
*
|
|
6698
|
+
/**
|
|
6699
|
+
* @deprecated 719/B4 moved query decomposition out of `recall()`. Budget
|
|
6700
|
+
* `high` no longer requires `decomposeOptions` and this signal is never
|
|
6701
|
+
* emitted. Prefer `"decompose-moved"` for the upgrade breadcrumb. Kept in
|
|
6702
|
+
* the union so existing telemetry consumers stay typed.
|
|
6703
|
+
*/
|
|
6669
6704
|
| "decompose-unavailable"
|
|
6705
|
+
/**
|
|
6706
|
+
* `budget: 'high'` with `decomposeOptions` set but no usable
|
|
6707
|
+
* {@link RecallOptions.subQueries}. Pre-B4 this call shape triggered LLM
|
|
6708
|
+
* rewrite inside `recall()`; post-B4 it stays on the single-query high
|
|
6709
|
+
* path (rerank + graph) and callers must pass facets (or use
|
|
6710
|
+
* {@link createRecallTool}). Surfaced so silent quality regressions show
|
|
6711
|
+
* up in diagnostics instead of looking healthier than before.
|
|
6712
|
+
*/
|
|
6713
|
+
| "decompose-moved"
|
|
6670
6714
|
/** There was no usable cosine lane, so results were ranked on BM25 (lexical)
|
|
6671
6715
|
* alone: either the query embedding failed (or came back empty), or no
|
|
6672
6716
|
* candidate had a vector to score against it because the row (re)embed failed.
|
|
@@ -8706,9 +8750,14 @@ declare function rankProfileCandidates(inputs: readonly ProfileSalienceInput[],
|
|
|
8706
8750
|
* Unified Recall API — single retrieval surface above vault + engine.
|
|
8707
8751
|
*
|
|
8708
8752
|
* Budget maps to pipeline depth (mirrors Hindsight's tiered defaults):
|
|
8709
|
-
* - `low` → V2 cosine + BM25 + recency (no rerank
|
|
8753
|
+
* - `low` → V2 cosine + BM25 + recency (no rerank)
|
|
8710
8754
|
* - `mid` → V2 + cross-encoder rerank
|
|
8711
|
-
* - `high` → V2 + rerank +
|
|
8755
|
+
* - `high` → V2 + rerank + multi-hop graph traversal
|
|
8756
|
+
*
|
|
8757
|
+
* LLM-free by design (719/B4): query decomposition for composite asks
|
|
8758
|
+
* lives in the tool/agent layer (`createRecallTool`), which may pass
|
|
8759
|
+
* pre-built `subQueries` into this API. `recall()` itself never pays an
|
|
8760
|
+
* LLM RTT.
|
|
8712
8761
|
*
|
|
8713
8762
|
* Fact + chunk lanes are fused with RRF (k=60). The previous naive
|
|
8714
8763
|
* "sort the union by raw score" path is gone — score scales differ
|
|
@@ -8763,7 +8812,8 @@ interface RecallToolOptions {
|
|
|
8763
8812
|
folderId?: string | null;
|
|
8764
8813
|
/** Exclude one conversation from chunk results (typically the active one). */
|
|
8765
8814
|
excludeConversationId?: string;
|
|
8766
|
-
/** LLM-decompose options; only used at budget="high".
|
|
8815
|
+
/** LLM-decompose options; only used at budget="high". Runs in THIS tool
|
|
8816
|
+
* executor (719/B4) — `recall()` itself is LLM-free. Auth follows the
|
|
8767
8817
|
* dual pattern: apiKey (server/CLI) or getToken (browser identity
|
|
8768
8818
|
* tokens) — at least one required. */
|
|
8769
8819
|
decomposeOptions?: PortalLlmAuth & {
|
package/dist/react/index.mjs
CHANGED
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
createVaultEmbeddingCache,
|
|
48
48
|
createVaultMemoriesBatchOp,
|
|
49
49
|
createVaultMemoryOp,
|
|
50
|
+
decomposeQuery,
|
|
50
51
|
decryptData,
|
|
51
52
|
decryptDataBatch,
|
|
52
53
|
decryptDataBytes,
|
|
@@ -164,7 +165,7 @@ import {
|
|
|
164
165
|
updateVaultMemoryOp,
|
|
165
166
|
useEncryption,
|
|
166
167
|
vaultMemoryToStored
|
|
167
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-KTBOHRRE.mjs";
|
|
168
169
|
import {
|
|
169
170
|
PiiRedactor,
|
|
170
171
|
createStreamingDeAnonymizer,
|
|
@@ -8631,7 +8632,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
8631
8632
|
type: "function",
|
|
8632
8633
|
function: {
|
|
8633
8634
|
name: RECALL_TOOL_NAME,
|
|
8634
|
-
description:
|
|
8635
|
+
description: `Search the user's memory across stored facts/preferences and past conversation excerpts. Returns a unified ranked list \u2014 facts carry an \`id\` you can reference; conversation excerpts carry a date and role. Use this whenever the user's question may relate to anything previously discussed or saved (preferences, prior decisions, past topics). Phrase the query naturally. For multi-faceted / overview questions ("tell me about the user", "what's my tech stack"), prefer several targeted searches \u2014 one facet each (e.g. name, work, hobbies) \u2014 over a single broad query; fuse the results yourself.`,
|
|
8635
8636
|
arguments: {
|
|
8636
8637
|
type: "object",
|
|
8637
8638
|
properties: {
|
|
@@ -8686,6 +8687,13 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
8686
8687
|
let surfaced = 0;
|
|
8687
8688
|
try {
|
|
8688
8689
|
let recallDegraded = [];
|
|
8690
|
+
let subQueries;
|
|
8691
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
8692
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
8693
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
8694
|
+
subQueries = decomp.subQueries;
|
|
8695
|
+
}
|
|
8696
|
+
}
|
|
8689
8697
|
const recallOpts = {
|
|
8690
8698
|
onDiagnostics: (d) => {
|
|
8691
8699
|
recallDegraded = d.degraded;
|
|
@@ -8699,10 +8707,12 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
8699
8707
|
...toolOptions?.excludeConversationId && {
|
|
8700
8708
|
excludeConversationId: toolOptions.excludeConversationId
|
|
8701
8709
|
},
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8710
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
8711
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
8712
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
8713
|
+
// be threaded later when the tool opts into that path.
|
|
8714
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
8715
|
+
...subQueries && { subQueries }
|
|
8706
8716
|
};
|
|
8707
8717
|
const result = await recall(query, ctx, recallOpts);
|
|
8708
8718
|
if (callbacks?.onChunksRetrieved) {
|