@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/server/index.cjs
CHANGED
|
@@ -20612,11 +20612,11 @@ async function decomposeQuery(query, options) {
|
|
|
20612
20612
|
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.
|
|
20613
20613
|
|
|
20614
20614
|
Query: ${trimmed}`,
|
|
20615
|
-
// Decompose runs
|
|
20615
|
+
// Decompose runs ahead of recall in the tool layer — tighter than the
|
|
20616
20616
|
// portalLlm default (consolidate/extract can wait longer).
|
|
20617
20617
|
timeoutMs: 2e4,
|
|
20618
20618
|
// No internal retry: a failure degrades to the safe `{specific,[query]}`
|
|
20619
|
-
// fallback below
|
|
20619
|
+
// fallback below. The agent/tool loop is the retry surface (719/B4).
|
|
20620
20620
|
maxAttempts: 1,
|
|
20621
20621
|
tag: "memory/decompose",
|
|
20622
20622
|
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
@@ -20628,12 +20628,28 @@ Query: ${trimmed}`,
|
|
|
20628
20628
|
if (parsed === null) return fallback;
|
|
20629
20629
|
return validate(parsed, trimmed) ?? fallback;
|
|
20630
20630
|
}
|
|
20631
|
+
function normalizeSubQueries(raw) {
|
|
20632
|
+
if (!raw || raw.length === 0) return [];
|
|
20633
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20634
|
+
const out = [];
|
|
20635
|
+
for (const s of raw) {
|
|
20636
|
+
if (typeof s !== "string") continue;
|
|
20637
|
+
const t = s.trim();
|
|
20638
|
+
if (t.length === 0) continue;
|
|
20639
|
+
const key = t.toLowerCase();
|
|
20640
|
+
if (seen.has(key)) continue;
|
|
20641
|
+
seen.add(key);
|
|
20642
|
+
out.push(t);
|
|
20643
|
+
if (out.length >= MAX_SUB_QUERIES) break;
|
|
20644
|
+
}
|
|
20645
|
+
return out;
|
|
20646
|
+
}
|
|
20631
20647
|
function validate(parsed, originalQuery) {
|
|
20632
20648
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
20633
20649
|
const obj = parsed;
|
|
20634
20650
|
const mode = obj.mode === "composite" ? "composite" : "specific";
|
|
20635
20651
|
if (!Array.isArray(obj.subQueries)) return null;
|
|
20636
|
-
const subQueries = obj.subQueries
|
|
20652
|
+
const subQueries = normalizeSubQueries(obj.subQueries);
|
|
20637
20653
|
if (subQueries.length === 0) return null;
|
|
20638
20654
|
if (mode === "specific") {
|
|
20639
20655
|
return { mode: "specific", subQueries: [originalQuery] };
|
|
@@ -21212,12 +21228,12 @@ __export(recall_exports, {
|
|
|
21212
21228
|
function flagsForBudget(budget) {
|
|
21213
21229
|
switch (budget) {
|
|
21214
21230
|
case "high":
|
|
21215
|
-
return { rerank: true,
|
|
21231
|
+
return { rerank: true, traverse: true };
|
|
21216
21232
|
case "mid":
|
|
21217
|
-
return { rerank: true,
|
|
21233
|
+
return { rerank: true, traverse: false };
|
|
21218
21234
|
case "low":
|
|
21219
21235
|
default:
|
|
21220
|
-
return { rerank: false,
|
|
21236
|
+
return { rerank: false, traverse: false };
|
|
21221
21237
|
}
|
|
21222
21238
|
}
|
|
21223
21239
|
function dedupeBy(items, ...keys) {
|
|
@@ -21236,10 +21252,10 @@ function dedupeBy(items, ...keys) {
|
|
|
21236
21252
|
async function recall(query, ctx, options = {}) {
|
|
21237
21253
|
const types = options.types ?? ["fact"];
|
|
21238
21254
|
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
21239
|
-
const
|
|
21240
|
-
const flags = flagsForBudget(
|
|
21241
|
-
const
|
|
21242
|
-
const
|
|
21255
|
+
const usedBudget = options.budget ?? DEFAULT_BUDGET;
|
|
21256
|
+
const flags = flagsForBudget(usedBudget);
|
|
21257
|
+
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
21258
|
+
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
21243
21259
|
const t0 = nowMs();
|
|
21244
21260
|
let prepMs = 0;
|
|
21245
21261
|
let factLaneMs = 0;
|
|
@@ -21260,7 +21276,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
21260
21276
|
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
21261
21277
|
degraded.push("rerank-unavailable");
|
|
21262
21278
|
}
|
|
21263
|
-
if (
|
|
21279
|
+
if (usedBudget === "high" && options.decomposeOptions && !subQueries && !options.graphRefine) {
|
|
21280
|
+
degraded.push("decompose-moved");
|
|
21281
|
+
}
|
|
21264
21282
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
21265
21283
|
const diagnostics = {
|
|
21266
21284
|
usedBudget,
|
|
@@ -21373,10 +21391,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
21373
21391
|
},
|
|
21374
21392
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
21375
21393
|
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
21376
|
-
|
|
21377
|
-
|
|
21378
|
-
decomposeOptions: options.decomposeOptions
|
|
21379
|
-
},
|
|
21394
|
+
// 719/B4 — composite facets arrive pre-built; no LLM call here.
|
|
21395
|
+
...subQueries && { subQueries },
|
|
21380
21396
|
...options.scopes && { scopes: options.scopes },
|
|
21381
21397
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
21382
21398
|
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
@@ -21613,6 +21629,7 @@ var init_recall = __esm({
|
|
|
21613
21629
|
init_logger();
|
|
21614
21630
|
init_constants();
|
|
21615
21631
|
init_embeddings();
|
|
21632
|
+
init_decomposeQuery();
|
|
21616
21633
|
init_searchTool();
|
|
21617
21634
|
init_graphTraversal();
|
|
21618
21635
|
init_observationTrend();
|
|
@@ -22558,52 +22575,51 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
22558
22575
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
22559
22576
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
22560
22577
|
};
|
|
22561
|
-
|
|
22562
|
-
|
|
22563
|
-
|
|
22564
|
-
|
|
22565
|
-
|
|
22566
|
-
|
|
22567
|
-
|
|
22568
|
-
|
|
22569
|
-
|
|
22570
|
-
|
|
22571
|
-
|
|
22572
|
-
|
|
22573
|
-
|
|
22574
|
-
|
|
22575
|
-
|
|
22576
|
-
|
|
22577
|
-
|
|
22578
|
-
|
|
22579
|
-
|
|
22580
|
-
|
|
22581
|
-
|
|
22582
|
-
|
|
22583
|
-
|
|
22584
|
-
|
|
22585
|
-
|
|
22586
|
-
|
|
22587
|
-
|
|
22588
|
-
|
|
22589
|
-
|
|
22590
|
-
|
|
22591
|
-
|
|
22592
|
-
|
|
22593
|
-
|
|
22594
|
-
|
|
22595
|
-
|
|
22596
|
-
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
|
|
22600
|
-
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
}
|
|
22578
|
+
const normalizedFacets = normalizeSubQueries(searchOptions?.subQueries);
|
|
22579
|
+
const facetQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
22580
|
+
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
22581
|
+
let subEmbeddings;
|
|
22582
|
+
try {
|
|
22583
|
+
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
22584
|
+
} catch (err) {
|
|
22585
|
+
getLogger().warn(
|
|
22586
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
22587
|
+
);
|
|
22588
|
+
subEmbeddings = [];
|
|
22589
|
+
}
|
|
22590
|
+
const subEmbeddingsUsable = facetQueries.length > 0 && subEmbeddings.length === facetQueries.length && subEmbeddings.every((v) => v.length > 0 && v.length === queryEmbedding.length);
|
|
22591
|
+
if (subEmbeddings.length > 0 && !subEmbeddingsUsable) {
|
|
22592
|
+
getLogger().warn(
|
|
22593
|
+
`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`
|
|
22594
|
+
);
|
|
22595
|
+
}
|
|
22596
|
+
if (subEmbeddingsUsable) {
|
|
22597
|
+
const subQueries = facetQueries.map((sq, i) => ({
|
|
22598
|
+
query: sq,
|
|
22599
|
+
embedding: subEmbeddings[i]
|
|
22600
|
+
}));
|
|
22601
|
+
const v2HeadStats = { hadResults: false };
|
|
22602
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
22603
|
+
limit,
|
|
22604
|
+
minSimilarity,
|
|
22605
|
+
rerank: !!searchOptions?.rerank,
|
|
22606
|
+
...searchOptions?.rerankTopN !== void 0 && {
|
|
22607
|
+
rerankTopN: searchOptions.rerankTopN
|
|
22608
|
+
},
|
|
22609
|
+
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
22610
|
+
...searchOptions?.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
22611
|
+
...tuning,
|
|
22612
|
+
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
22613
|
+
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
22614
|
+
rerankStats,
|
|
22615
|
+
v2HeadStats
|
|
22616
|
+
});
|
|
22617
|
+
return stampTimestamps({
|
|
22618
|
+
results: composite,
|
|
22619
|
+
vaultSize,
|
|
22620
|
+
reranked: rerankStats.applied,
|
|
22621
|
+
hadV2Head: v2HeadStats.hadResults
|
|
22622
|
+
});
|
|
22607
22623
|
}
|
|
22608
22624
|
}
|
|
22609
22625
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -22663,6 +22679,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
22663
22679
|
rankedOnCosine: false
|
|
22664
22680
|
};
|
|
22665
22681
|
}
|
|
22682
|
+
if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
|
|
22683
|
+
warnedProgrammaticDecomposeIgnored = true;
|
|
22684
|
+
getLogger().warn(
|
|
22685
|
+
'memoryVault: decompose:"llm" is ignored by searchVaultMemories \u2014 pass subQueries or use createMemoryVaultSearchTool / createRecallTool (719/B4)'
|
|
22686
|
+
);
|
|
22687
|
+
}
|
|
22666
22688
|
const prepared = await prepareVaultCandidates(
|
|
22667
22689
|
query,
|
|
22668
22690
|
vaultCtx,
|
|
@@ -22767,7 +22789,8 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22767
22789
|
return "Error: A search query is required.";
|
|
22768
22790
|
}
|
|
22769
22791
|
try {
|
|
22770
|
-
const
|
|
22792
|
+
const wantsDecompose = searchOptions?.decompose === "llm" && !!searchOptions.decomposeOptions;
|
|
22793
|
+
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
22771
22794
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
22772
22795
|
if (searchOptions?.useFusion === false) {
|
|
22773
22796
|
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
@@ -22791,6 +22814,13 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22791
22814
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
22792
22815
|
);
|
|
22793
22816
|
}
|
|
22817
|
+
let subQueries;
|
|
22818
|
+
if (wantsDecompose && searchOptions?.decomposeOptions) {
|
|
22819
|
+
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
22820
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
22821
|
+
subQueries = decomp.subQueries;
|
|
22822
|
+
}
|
|
22823
|
+
}
|
|
22794
22824
|
const { recall: recall2 } = await Promise.resolve().then(() => (init_recall(), recall_exports));
|
|
22795
22825
|
let recallDegraded = [];
|
|
22796
22826
|
const result = await recall2(
|
|
@@ -22807,9 +22837,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22807
22837
|
...tuningForward,
|
|
22808
22838
|
...folderId !== void 0 && { folderId },
|
|
22809
22839
|
...searchOptions?.scopes && { scopes: searchOptions.scopes },
|
|
22810
|
-
...
|
|
22811
|
-
decomposeOptions: searchOptions.decomposeOptions
|
|
22812
|
-
}
|
|
22840
|
+
...subQueries && { subQueries }
|
|
22813
22841
|
}
|
|
22814
22842
|
);
|
|
22815
22843
|
if (result.vaultSize === 0) {
|
|
@@ -22839,7 +22867,7 @@ ${formatted}`;
|
|
|
22839
22867
|
}
|
|
22840
22868
|
};
|
|
22841
22869
|
}
|
|
22842
|
-
var SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
22870
|
+
var warnedProgrammaticDecomposeIgnored, SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
22843
22871
|
var init_searchTool = __esm({
|
|
22844
22872
|
"src/lib/memoryVault/searchTool.ts"() {
|
|
22845
22873
|
"use strict";
|
|
@@ -22857,6 +22885,7 @@ var init_searchTool = __esm({
|
|
|
22857
22885
|
init_bm25();
|
|
22858
22886
|
init_decomposeQuery();
|
|
22859
22887
|
init_lruCache();
|
|
22888
|
+
warnedProgrammaticDecomposeIgnored = false;
|
|
22860
22889
|
SUPERSESSION_SIMILARITY_THRESHOLD = 0.7;
|
|
22861
22890
|
SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
22862
22891
|
SUPERSESSION_BOOST_FACTOR = 0.8;
|
|
@@ -29733,6 +29762,7 @@ function rankProfileCandidates(inputs, now = Date.now(), options = {}) {
|
|
|
29733
29762
|
init_recall();
|
|
29734
29763
|
|
|
29735
29764
|
// src/lib/memory/recallTool.ts
|
|
29765
|
+
init_decomposeQuery();
|
|
29736
29766
|
init_recall();
|
|
29737
29767
|
init_recallConstants();
|
|
29738
29768
|
var DEFAULT_LIMIT2 = 8;
|
|
@@ -29830,7 +29860,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29830
29860
|
type: "function",
|
|
29831
29861
|
function: {
|
|
29832
29862
|
name: RECALL_TOOL_NAME,
|
|
29833
|
-
description:
|
|
29863
|
+
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.`,
|
|
29834
29864
|
arguments: {
|
|
29835
29865
|
type: "object",
|
|
29836
29866
|
properties: {
|
|
@@ -29885,6 +29915,13 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29885
29915
|
let surfaced = 0;
|
|
29886
29916
|
try {
|
|
29887
29917
|
let recallDegraded = [];
|
|
29918
|
+
let subQueries;
|
|
29919
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
29920
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
29921
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
29922
|
+
subQueries = decomp.subQueries;
|
|
29923
|
+
}
|
|
29924
|
+
}
|
|
29888
29925
|
const recallOpts = {
|
|
29889
29926
|
onDiagnostics: (d) => {
|
|
29890
29927
|
recallDegraded = d.degraded;
|
|
@@ -29898,10 +29935,12 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29898
29935
|
...toolOptions?.excludeConversationId && {
|
|
29899
29936
|
excludeConversationId: toolOptions.excludeConversationId
|
|
29900
29937
|
},
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
|
|
29904
|
-
|
|
29938
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
29939
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
29940
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
29941
|
+
// be threaded later when the tool opts into that path.
|
|
29942
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
29943
|
+
...subQueries && { subQueries }
|
|
29905
29944
|
};
|
|
29906
29945
|
const result = await recall(query, ctx, recallOpts);
|
|
29907
29946
|
if (callbacks?.onChunksRetrieved) {
|
package/dist/server/index.d.mts
CHANGED
|
@@ -4945,15 +4945,26 @@ interface MemoryVaultSearchOptions {
|
|
|
4945
4945
|
/** RRF smoothing constant for lane fusion. Default 60. */
|
|
4946
4946
|
rrfK?: number;
|
|
4947
4947
|
/**
|
|
4948
|
-
*
|
|
4949
|
-
*
|
|
4950
|
-
*
|
|
4951
|
-
*
|
|
4948
|
+
* Pre-decomposed facet queries for the composite ranker (719/B4). When
|
|
4949
|
+
* ≥2 are supplied (and embeddings are available), runs {@link rankComposite}
|
|
4950
|
+
* over them — no LLM call inside the search path. Callers that want LLM
|
|
4951
|
+
* rewrite (e.g. `createRecallTool`) call `decomposeQuery` first and pass
|
|
4952
|
+
* the facets here.
|
|
4953
|
+
*/
|
|
4954
|
+
subQueries?: string[];
|
|
4955
|
+
/**
|
|
4956
|
+
* @deprecated 719/B4 — ignored by {@link searchVaultMemories} /
|
|
4957
|
+
* {@link searchVaultMemoriesWithSize}. Pass {@link MemoryVaultSearchOptions.subQueries}
|
|
4958
|
+
* (or use `createRecallTool`). The legacy {@link createMemoryVaultSearchTool}
|
|
4959
|
+
* executor still honors `decompose: "llm"` + `decomposeOptions` for eval
|
|
4960
|
+
* parity, then forwards facets into the LLM-free search path.
|
|
4952
4961
|
*/
|
|
4953
4962
|
decompose?: "off" | "llm";
|
|
4954
|
-
/**
|
|
4955
|
-
*
|
|
4956
|
-
*
|
|
4963
|
+
/**
|
|
4964
|
+
* @deprecated 719/B4 — see `decompose`. Ignored on the programmatic search
|
|
4965
|
+
* path; tool-layer rewrite still reads this from the search-tool options.
|
|
4966
|
+
* Prefer `RecallToolOptions.decomposeOptions` with `createRecallTool`.
|
|
4967
|
+
*/
|
|
4957
4968
|
decomposeOptions?: PortalLlmAuth & {
|
|
4958
4969
|
baseUrl?: string;
|
|
4959
4970
|
model?: string;
|
|
@@ -5118,9 +5129,11 @@ type MemoryKind = "fact" | "chunk";
|
|
|
5118
5129
|
* Budget controls retrieval depth/cost. Higher budgets enable more
|
|
5119
5130
|
* candidate sources and the cross-encoder reranker.
|
|
5120
5131
|
*
|
|
5121
|
-
* - `low`: cosine + BM25
|
|
5122
|
-
* - `mid`: +
|
|
5123
|
-
* - `high`: +
|
|
5132
|
+
* - `low`: cosine + BM25 + recency. No reranker. Mobile default.
|
|
5133
|
+
* - `mid`: + cross-encoder rerank.
|
|
5134
|
+
* - `high`: + multi-hop graph traversal. LLM-free — query decomposition
|
|
5135
|
+
* (when wanted) lives in the tool/agent layer ({@link createRecallTool}),
|
|
5136
|
+
* not inside `recall()` itself (719/B4).
|
|
5124
5137
|
*/
|
|
5125
5138
|
type Budget = "low" | "mid" | "high";
|
|
5126
5139
|
interface ScoreBreakdown {
|
|
@@ -5220,10 +5233,28 @@ interface RecallOptions {
|
|
|
5220
5233
|
/** Drop results below this score. Default: 0.1 for facts, 0.5 for chunks (mirrors today's defaults). */
|
|
5221
5234
|
minScore?: number;
|
|
5222
5235
|
/**
|
|
5223
|
-
*
|
|
5224
|
-
*
|
|
5225
|
-
*
|
|
5226
|
-
*
|
|
5236
|
+
* Pre-decomposed facet queries for the composite ranker. When ≥2 are
|
|
5237
|
+
* supplied, the vault lane runs `rankComposite` over them (no LLM call
|
|
5238
|
+
* inside `recall()` — 719/B4). Callers that still want LLM rewrite
|
|
5239
|
+
* (e.g. {@link createRecallTool} at `budget: 'high'`) call
|
|
5240
|
+
* `decomposeQuery` themselves and pass the result here. A single entry
|
|
5241
|
+
* (or omitting this) keeps the single-query path.
|
|
5242
|
+
*/
|
|
5243
|
+
subQueries?: string[];
|
|
5244
|
+
/**
|
|
5245
|
+
* Auth + endpoint for optional LLM helpers that reuse portal auth —
|
|
5246
|
+
* currently {@link RecallOptions.graphRefine} neighbor selection.
|
|
5247
|
+
* Query decomposition is **not** driven by this field inside `recall()`
|
|
5248
|
+
* (719/B4); {@link createRecallTool} reads the same shape from
|
|
5249
|
+
* `RecallToolOptions.decomposeOptions` for tool-layer rewrite.
|
|
5250
|
+
*
|
|
5251
|
+
* Callers that still pass `{ budget: 'high', decomposeOptions }` without
|
|
5252
|
+
* {@link RecallOptions.subQueries} keep compiling but no longer rewrite —
|
|
5253
|
+
* `recall()` emits `decompose-moved` on {@link RecallDiagnostics.degraded}
|
|
5254
|
+
* so upgrades without a changelog read still leave a telemetry breadcrumb.
|
|
5255
|
+
*
|
|
5256
|
+
* Auth is the dual pattern — one of `apiKey` / `getToken` is required;
|
|
5257
|
+
* see {@link PortalLlmAuth}.
|
|
5227
5258
|
*/
|
|
5228
5259
|
decomposeOptions?: PortalLlmAuth & {
|
|
5229
5260
|
baseUrl?: string;
|
|
@@ -5327,9 +5358,22 @@ type RecallDegradation =
|
|
|
5327
5358
|
/** Rerank was requested (budget mid/high) but the cross-encoder didn't run
|
|
5328
5359
|
* this call — unavailable (e.g. React Native) or a transient failure. */
|
|
5329
5360
|
"rerank-unavailable"
|
|
5330
|
-
/**
|
|
5331
|
-
*
|
|
5361
|
+
/**
|
|
5362
|
+
* @deprecated 719/B4 moved query decomposition out of `recall()`. Budget
|
|
5363
|
+
* `high` no longer requires `decomposeOptions` and this signal is never
|
|
5364
|
+
* emitted. Prefer `"decompose-moved"` for the upgrade breadcrumb. Kept in
|
|
5365
|
+
* the union so existing telemetry consumers stay typed.
|
|
5366
|
+
*/
|
|
5332
5367
|
| "decompose-unavailable"
|
|
5368
|
+
/**
|
|
5369
|
+
* `budget: 'high'` with `decomposeOptions` set but no usable
|
|
5370
|
+
* {@link RecallOptions.subQueries}. Pre-B4 this call shape triggered LLM
|
|
5371
|
+
* rewrite inside `recall()`; post-B4 it stays on the single-query high
|
|
5372
|
+
* path (rerank + graph) and callers must pass facets (or use
|
|
5373
|
+
* {@link createRecallTool}). Surfaced so silent quality regressions show
|
|
5374
|
+
* up in diagnostics instead of looking healthier than before.
|
|
5375
|
+
*/
|
|
5376
|
+
| "decompose-moved"
|
|
5333
5377
|
/** There was no usable cosine lane, so results were ranked on BM25 (lexical)
|
|
5334
5378
|
* alone: either the query embedding failed (or came back empty), or no
|
|
5335
5379
|
* candidate had a vector to score against it because the row (re)embed failed.
|
|
@@ -8103,9 +8147,14 @@ declare function rankProfileCandidates(inputs: readonly ProfileSalienceInput[],
|
|
|
8103
8147
|
* Unified Recall API — single retrieval surface above vault + engine.
|
|
8104
8148
|
*
|
|
8105
8149
|
* Budget maps to pipeline depth (mirrors Hindsight's tiered defaults):
|
|
8106
|
-
* - `low` → V2 cosine + BM25 + recency (no rerank
|
|
8150
|
+
* - `low` → V2 cosine + BM25 + recency (no rerank)
|
|
8107
8151
|
* - `mid` → V2 + cross-encoder rerank
|
|
8108
|
-
* - `high` → V2 + rerank +
|
|
8152
|
+
* - `high` → V2 + rerank + multi-hop graph traversal
|
|
8153
|
+
*
|
|
8154
|
+
* LLM-free by design (719/B4): query decomposition for composite asks
|
|
8155
|
+
* lives in the tool/agent layer (`createRecallTool`), which may pass
|
|
8156
|
+
* pre-built `subQueries` into this API. `recall()` itself never pays an
|
|
8157
|
+
* LLM RTT.
|
|
8109
8158
|
*
|
|
8110
8159
|
* Fact + chunk lanes are fused with RRF (k=60). The previous naive
|
|
8111
8160
|
* "sort the union by raw score" path is gone — score scales differ
|
|
@@ -8160,7 +8209,8 @@ interface RecallToolOptions {
|
|
|
8160
8209
|
folderId?: string | null;
|
|
8161
8210
|
/** Exclude one conversation from chunk results (typically the active one). */
|
|
8162
8211
|
excludeConversationId?: string;
|
|
8163
|
-
/** LLM-decompose options; only used at budget="high".
|
|
8212
|
+
/** LLM-decompose options; only used at budget="high". Runs in THIS tool
|
|
8213
|
+
* executor (719/B4) — `recall()` itself is LLM-free. Auth follows the
|
|
8164
8214
|
* dual pattern: apiKey (server/CLI) or getToken (browser identity
|
|
8165
8215
|
* tokens) — at least one required. */
|
|
8166
8216
|
decomposeOptions?: PortalLlmAuth & {
|
package/dist/server/index.d.ts
CHANGED
|
@@ -4945,15 +4945,26 @@ interface MemoryVaultSearchOptions {
|
|
|
4945
4945
|
/** RRF smoothing constant for lane fusion. Default 60. */
|
|
4946
4946
|
rrfK?: number;
|
|
4947
4947
|
/**
|
|
4948
|
-
*
|
|
4949
|
-
*
|
|
4950
|
-
*
|
|
4951
|
-
*
|
|
4948
|
+
* Pre-decomposed facet queries for the composite ranker (719/B4). When
|
|
4949
|
+
* ≥2 are supplied (and embeddings are available), runs {@link rankComposite}
|
|
4950
|
+
* over them — no LLM call inside the search path. Callers that want LLM
|
|
4951
|
+
* rewrite (e.g. `createRecallTool`) call `decomposeQuery` first and pass
|
|
4952
|
+
* the facets here.
|
|
4953
|
+
*/
|
|
4954
|
+
subQueries?: string[];
|
|
4955
|
+
/**
|
|
4956
|
+
* @deprecated 719/B4 — ignored by {@link searchVaultMemories} /
|
|
4957
|
+
* {@link searchVaultMemoriesWithSize}. Pass {@link MemoryVaultSearchOptions.subQueries}
|
|
4958
|
+
* (or use `createRecallTool`). The legacy {@link createMemoryVaultSearchTool}
|
|
4959
|
+
* executor still honors `decompose: "llm"` + `decomposeOptions` for eval
|
|
4960
|
+
* parity, then forwards facets into the LLM-free search path.
|
|
4952
4961
|
*/
|
|
4953
4962
|
decompose?: "off" | "llm";
|
|
4954
|
-
/**
|
|
4955
|
-
*
|
|
4956
|
-
*
|
|
4963
|
+
/**
|
|
4964
|
+
* @deprecated 719/B4 — see `decompose`. Ignored on the programmatic search
|
|
4965
|
+
* path; tool-layer rewrite still reads this from the search-tool options.
|
|
4966
|
+
* Prefer `RecallToolOptions.decomposeOptions` with `createRecallTool`.
|
|
4967
|
+
*/
|
|
4957
4968
|
decomposeOptions?: PortalLlmAuth & {
|
|
4958
4969
|
baseUrl?: string;
|
|
4959
4970
|
model?: string;
|
|
@@ -5118,9 +5129,11 @@ type MemoryKind = "fact" | "chunk";
|
|
|
5118
5129
|
* Budget controls retrieval depth/cost. Higher budgets enable more
|
|
5119
5130
|
* candidate sources and the cross-encoder reranker.
|
|
5120
5131
|
*
|
|
5121
|
-
* - `low`: cosine + BM25
|
|
5122
|
-
* - `mid`: +
|
|
5123
|
-
* - `high`: +
|
|
5132
|
+
* - `low`: cosine + BM25 + recency. No reranker. Mobile default.
|
|
5133
|
+
* - `mid`: + cross-encoder rerank.
|
|
5134
|
+
* - `high`: + multi-hop graph traversal. LLM-free — query decomposition
|
|
5135
|
+
* (when wanted) lives in the tool/agent layer ({@link createRecallTool}),
|
|
5136
|
+
* not inside `recall()` itself (719/B4).
|
|
5124
5137
|
*/
|
|
5125
5138
|
type Budget = "low" | "mid" | "high";
|
|
5126
5139
|
interface ScoreBreakdown {
|
|
@@ -5220,10 +5233,28 @@ interface RecallOptions {
|
|
|
5220
5233
|
/** Drop results below this score. Default: 0.1 for facts, 0.5 for chunks (mirrors today's defaults). */
|
|
5221
5234
|
minScore?: number;
|
|
5222
5235
|
/**
|
|
5223
|
-
*
|
|
5224
|
-
*
|
|
5225
|
-
*
|
|
5226
|
-
*
|
|
5236
|
+
* Pre-decomposed facet queries for the composite ranker. When ≥2 are
|
|
5237
|
+
* supplied, the vault lane runs `rankComposite` over them (no LLM call
|
|
5238
|
+
* inside `recall()` — 719/B4). Callers that still want LLM rewrite
|
|
5239
|
+
* (e.g. {@link createRecallTool} at `budget: 'high'`) call
|
|
5240
|
+
* `decomposeQuery` themselves and pass the result here. A single entry
|
|
5241
|
+
* (or omitting this) keeps the single-query path.
|
|
5242
|
+
*/
|
|
5243
|
+
subQueries?: string[];
|
|
5244
|
+
/**
|
|
5245
|
+
* Auth + endpoint for optional LLM helpers that reuse portal auth —
|
|
5246
|
+
* currently {@link RecallOptions.graphRefine} neighbor selection.
|
|
5247
|
+
* Query decomposition is **not** driven by this field inside `recall()`
|
|
5248
|
+
* (719/B4); {@link createRecallTool} reads the same shape from
|
|
5249
|
+
* `RecallToolOptions.decomposeOptions` for tool-layer rewrite.
|
|
5250
|
+
*
|
|
5251
|
+
* Callers that still pass `{ budget: 'high', decomposeOptions }` without
|
|
5252
|
+
* {@link RecallOptions.subQueries} keep compiling but no longer rewrite —
|
|
5253
|
+
* `recall()` emits `decompose-moved` on {@link RecallDiagnostics.degraded}
|
|
5254
|
+
* so upgrades without a changelog read still leave a telemetry breadcrumb.
|
|
5255
|
+
*
|
|
5256
|
+
* Auth is the dual pattern — one of `apiKey` / `getToken` is required;
|
|
5257
|
+
* see {@link PortalLlmAuth}.
|
|
5227
5258
|
*/
|
|
5228
5259
|
decomposeOptions?: PortalLlmAuth & {
|
|
5229
5260
|
baseUrl?: string;
|
|
@@ -5327,9 +5358,22 @@ type RecallDegradation =
|
|
|
5327
5358
|
/** Rerank was requested (budget mid/high) but the cross-encoder didn't run
|
|
5328
5359
|
* this call — unavailable (e.g. React Native) or a transient failure. */
|
|
5329
5360
|
"rerank-unavailable"
|
|
5330
|
-
/**
|
|
5331
|
-
*
|
|
5361
|
+
/**
|
|
5362
|
+
* @deprecated 719/B4 moved query decomposition out of `recall()`. Budget
|
|
5363
|
+
* `high` no longer requires `decomposeOptions` and this signal is never
|
|
5364
|
+
* emitted. Prefer `"decompose-moved"` for the upgrade breadcrumb. Kept in
|
|
5365
|
+
* the union so existing telemetry consumers stay typed.
|
|
5366
|
+
*/
|
|
5332
5367
|
| "decompose-unavailable"
|
|
5368
|
+
/**
|
|
5369
|
+
* `budget: 'high'` with `decomposeOptions` set but no usable
|
|
5370
|
+
* {@link RecallOptions.subQueries}. Pre-B4 this call shape triggered LLM
|
|
5371
|
+
* rewrite inside `recall()`; post-B4 it stays on the single-query high
|
|
5372
|
+
* path (rerank + graph) and callers must pass facets (or use
|
|
5373
|
+
* {@link createRecallTool}). Surfaced so silent quality regressions show
|
|
5374
|
+
* up in diagnostics instead of looking healthier than before.
|
|
5375
|
+
*/
|
|
5376
|
+
| "decompose-moved"
|
|
5333
5377
|
/** There was no usable cosine lane, so results were ranked on BM25 (lexical)
|
|
5334
5378
|
* alone: either the query embedding failed (or came back empty), or no
|
|
5335
5379
|
* candidate had a vector to score against it because the row (re)embed failed.
|
|
@@ -8103,9 +8147,14 @@ declare function rankProfileCandidates(inputs: readonly ProfileSalienceInput[],
|
|
|
8103
8147
|
* Unified Recall API — single retrieval surface above vault + engine.
|
|
8104
8148
|
*
|
|
8105
8149
|
* Budget maps to pipeline depth (mirrors Hindsight's tiered defaults):
|
|
8106
|
-
* - `low` → V2 cosine + BM25 + recency (no rerank
|
|
8150
|
+
* - `low` → V2 cosine + BM25 + recency (no rerank)
|
|
8107
8151
|
* - `mid` → V2 + cross-encoder rerank
|
|
8108
|
-
* - `high` → V2 + rerank +
|
|
8152
|
+
* - `high` → V2 + rerank + multi-hop graph traversal
|
|
8153
|
+
*
|
|
8154
|
+
* LLM-free by design (719/B4): query decomposition for composite asks
|
|
8155
|
+
* lives in the tool/agent layer (`createRecallTool`), which may pass
|
|
8156
|
+
* pre-built `subQueries` into this API. `recall()` itself never pays an
|
|
8157
|
+
* LLM RTT.
|
|
8109
8158
|
*
|
|
8110
8159
|
* Fact + chunk lanes are fused with RRF (k=60). The previous naive
|
|
8111
8160
|
* "sort the union by raw score" path is gone — score scales differ
|
|
@@ -8160,7 +8209,8 @@ interface RecallToolOptions {
|
|
|
8160
8209
|
folderId?: string | null;
|
|
8161
8210
|
/** Exclude one conversation from chunk results (typically the active one). */
|
|
8162
8211
|
excludeConversationId?: string;
|
|
8163
|
-
/** LLM-decompose options; only used at budget="high".
|
|
8212
|
+
/** LLM-decompose options; only used at budget="high". Runs in THIS tool
|
|
8213
|
+
* executor (719/B4) — `recall()` itself is LLM-free. Auth follows the
|
|
8164
8214
|
* dual pattern: apiKey (server/CLI) or getToken (browser identity
|
|
8165
8215
|
* tokens) — at least one required. */
|
|
8166
8216
|
decomposeOptions?: PortalLlmAuth & {
|
package/dist/server/index.mjs
CHANGED
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
createVaultEmbeddingCache,
|
|
44
44
|
createVaultMemoriesBatchOp,
|
|
45
45
|
createVaultMemoryOp,
|
|
46
|
+
decomposeQuery,
|
|
46
47
|
decryptData,
|
|
47
48
|
decryptDataBatch,
|
|
48
49
|
decryptDataBytes,
|
|
@@ -136,7 +137,7 @@ import {
|
|
|
136
137
|
updateVaultMemoryOp,
|
|
137
138
|
upsertMessageOp,
|
|
138
139
|
vaultMemoryToStored
|
|
139
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-FKVYUOSD.mjs";
|
|
140
141
|
import {
|
|
141
142
|
createStreamingDeAnonymizer,
|
|
142
143
|
notifyConsolidationFallback,
|
|
@@ -6586,7 +6587,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
6586
6587
|
type: "function",
|
|
6587
6588
|
function: {
|
|
6588
6589
|
name: RECALL_TOOL_NAME,
|
|
6589
|
-
description:
|
|
6590
|
+
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.`,
|
|
6590
6591
|
arguments: {
|
|
6591
6592
|
type: "object",
|
|
6592
6593
|
properties: {
|
|
@@ -6641,6 +6642,13 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
6641
6642
|
let surfaced = 0;
|
|
6642
6643
|
try {
|
|
6643
6644
|
let recallDegraded = [];
|
|
6645
|
+
let subQueries;
|
|
6646
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
6647
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
6648
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
6649
|
+
subQueries = decomp.subQueries;
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6644
6652
|
const recallOpts = {
|
|
6645
6653
|
onDiagnostics: (d) => {
|
|
6646
6654
|
recallDegraded = d.degraded;
|
|
@@ -6654,10 +6662,12 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
6654
6662
|
...toolOptions?.excludeConversationId && {
|
|
6655
6663
|
excludeConversationId: toolOptions.excludeConversationId
|
|
6656
6664
|
},
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6665
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
6666
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
6667
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
6668
|
+
// be threaded later when the tool opts into that path.
|
|
6669
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
6670
|
+
...subQueries && { subQueries }
|
|
6661
6671
|
};
|
|
6662
6672
|
const result = await recall(query, ctx, recallOpts);
|
|
6663
6673
|
if (callbacks?.onChunksRetrieved) {
|