@anuma/sdk 4.2.1 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/{chunk-3CDSIN22.mjs → chunk-SIMGZQ4P.mjs} +177 -148
- package/dist/expo/index.cjs +164 -73
- package/dist/expo/index.d.mts +75 -20
- package/dist/expo/index.d.ts +75 -20
- package/dist/expo/index.mjs +70 -8
- 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 +164 -73
- package/dist/react/index.d.mts +75 -20
- package/dist/react/index.d.ts +75 -20
- package/dist/react/index.mjs +70 -8
- 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 +164 -73
- package/dist/server/index.d.mts +75 -20
- package/dist/server/index.d.ts +75 -20
- package/dist/server/index.mjs +70 -8
- package/dist/server/{recall-ZHEPQNEU.mjs → recall-74L75BJ3.mjs} +1 -1
- package/package.json +1 -1
|
@@ -18939,6 +18939,107 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
|
|
|
18939
18939
|
return embeddedCount;
|
|
18940
18940
|
}
|
|
18941
18941
|
|
|
18942
|
+
// src/lib/memoryVault/decomposeQuery.ts
|
|
18943
|
+
var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
|
|
18944
|
+
var MAX_SUB_QUERIES = 5;
|
|
18945
|
+
var SYSTEM_PROMPT = `You classify a memory query and, if needed, decompose it into concrete sub-queries.
|
|
18946
|
+
|
|
18947
|
+
CLASSIFICATION RULES \u2014 be strict:
|
|
18948
|
+
- "specific": asks for one fact OR a list of items in ONE category (one dimension).
|
|
18949
|
+
Examples: a name, a date, a preference, a location, an ID, a value, "what hobbies",
|
|
18950
|
+
"which conferences", "what open source projects", "what does X do for exercise".
|
|
18951
|
+
Even when the answer is a list, if all items belong to one dimension, it is specific.
|
|
18952
|
+
- "composite": asks about a person, system, or setup MULTI-DIMENSIONALLY \u2014 a summary,
|
|
18953
|
+
an overview, a profile, "tell me about X", "what is my X setup", "describe the team's
|
|
18954
|
+
X". The answer must span multiple distinct fact dimensions (e.g. for a "tech stack":
|
|
18955
|
+
language + database + framework + tools \u2014 four different dimensions).
|
|
18956
|
+
|
|
18957
|
+
When in doubt, prefer "specific". Mis-classifying a single-dimension list as composite
|
|
18958
|
+
hurts retrieval more than the reverse.
|
|
18959
|
+
|
|
18960
|
+
SUB-QUERY RULES (composite only, 3\u20135 questions):
|
|
18961
|
+
- Each sub-query targets a DIFFERENT fact dimension.
|
|
18962
|
+
- Use SHORT parenthetical examples \u2014 2\u20134 concrete options that anchor the
|
|
18963
|
+
embedding to likely memory content. Examples must be terms a user would
|
|
18964
|
+
actually have in their notes (e.g., "Postgres" not "PostgreSQL 15.2 with
|
|
18965
|
+
read replicas"). No verbose qualifiers like "and versions" or "and any
|
|
18966
|
+
relevant configuration details".
|
|
18967
|
+
- 8\u201314 words including the parenthetical. Like a human asking a follow-up.
|
|
18968
|
+
|
|
18969
|
+
Examples:
|
|
18970
|
+
"What is my dog's name?" \u2192 {"mode":"specific","subQueries":["What is my dog's name?"]}
|
|
18971
|
+
"What does the user do for exercise?" \u2192 {"mode":"specific","subQueries":["What does the user do for exercise?"]}
|
|
18972
|
+
"What conferences has the user attended?" \u2192 {"mode":"specific","subQueries":["What conferences has the user attended?"]}
|
|
18973
|
+
"What did I do last Tuesday?" \u2192 {"mode":"specific","subQueries":["What did I do last Tuesday?"]}
|
|
18974
|
+
"Tell me about the user as a person" \u2192 {"mode":"composite","subQueries":["What is the user's name?","Where does the user live?","What does the user do for work?","Any health conditions or allergies?","What are the user's hobbies (sports, music, games)?"]}
|
|
18975
|
+
"What is the user's tech stack?" \u2192 {"mode":"composite","subQueries":["What programming languages does the user use (Python, Go, TypeScript)?","What database does the user use (Postgres, MySQL, Mongo)?","What framework or ORM (React, Django, Prisma)?","What infrastructure (AWS, Docker, K8s)?","What testing tools (Jest, pytest, Cypress)?"]}
|
|
18976
|
+
"Describe the user's development environment" \u2192 {"mode":"composite","subQueries":["What operating system does the user use (macOS, Linux, Windows)?","What editor or IDE (VS Code, Vim, IntelliJ)?","What shell or terminal setup (zsh, bash, tmux)?","What keyboard or display setup (mechanical, vertical monitor)?","Any UI preferences (dark mode, font, vim keybindings)?"]}
|
|
18977
|
+
|
|
18978
|
+
Output strict JSON. No prose.`;
|
|
18979
|
+
async function decomposeQuery(query, options) {
|
|
18980
|
+
const fallback = { mode: "specific", subQueries: [query] };
|
|
18981
|
+
const trimmed = query.trim();
|
|
18982
|
+
if (trimmed.length === 0) return fallback;
|
|
18983
|
+
let parsed;
|
|
18984
|
+
try {
|
|
18985
|
+
parsed = await callPortalJsonCompletion({
|
|
18986
|
+
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
18987
|
+
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
18988
|
+
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
18989
|
+
model: options.model ?? DEFAULT_MODEL,
|
|
18990
|
+
systemPrompt: SYSTEM_PROMPT,
|
|
18991
|
+
// Wrap the bare query in a task framing so the model treats it as
|
|
18992
|
+
// input to classify, not as a question to answer conversationally.
|
|
18993
|
+
// Bare-query inputs caused Anthropic models to respond with prose
|
|
18994
|
+
// like "Do you mean...?" before this wrap.
|
|
18995
|
+
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.
|
|
18996
|
+
|
|
18997
|
+
Query: ${trimmed}`,
|
|
18998
|
+
// Decompose runs ahead of recall in the tool layer — tighter than the
|
|
18999
|
+
// portalLlm default (consolidate/extract can wait longer).
|
|
19000
|
+
timeoutMs: 2e4,
|
|
19001
|
+
// No internal retry: a failure degrades to the safe `{specific,[query]}`
|
|
19002
|
+
// fallback below. The agent/tool loop is the retry surface (719/B4).
|
|
19003
|
+
maxAttempts: 1,
|
|
19004
|
+
tag: "memory/decompose",
|
|
19005
|
+
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
19006
|
+
});
|
|
19007
|
+
} catch (err) {
|
|
19008
|
+
getLogger().warn("memoryVault/decompose: portal call failed, falling back to specific", err);
|
|
19009
|
+
return fallback;
|
|
19010
|
+
}
|
|
19011
|
+
if (parsed === null) return fallback;
|
|
19012
|
+
return validate(parsed, trimmed) ?? fallback;
|
|
19013
|
+
}
|
|
19014
|
+
function normalizeSubQueries(raw) {
|
|
19015
|
+
if (!raw || raw.length === 0) return [];
|
|
19016
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19017
|
+
const out = [];
|
|
19018
|
+
for (const s of raw) {
|
|
19019
|
+
if (typeof s !== "string") continue;
|
|
19020
|
+
const t = s.trim();
|
|
19021
|
+
if (t.length === 0) continue;
|
|
19022
|
+
const key = t.toLowerCase();
|
|
19023
|
+
if (seen.has(key)) continue;
|
|
19024
|
+
seen.add(key);
|
|
19025
|
+
out.push(t);
|
|
19026
|
+
if (out.length >= MAX_SUB_QUERIES) break;
|
|
19027
|
+
}
|
|
19028
|
+
return out;
|
|
19029
|
+
}
|
|
19030
|
+
function validate(parsed, originalQuery) {
|
|
19031
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
19032
|
+
const obj = parsed;
|
|
19033
|
+
const mode = obj.mode === "composite" ? "composite" : "specific";
|
|
19034
|
+
if (!Array.isArray(obj.subQueries)) return null;
|
|
19035
|
+
const subQueries = normalizeSubQueries(obj.subQueries);
|
|
19036
|
+
if (subQueries.length === 0) return null;
|
|
19037
|
+
if (mode === "specific") {
|
|
19038
|
+
return { mode: "specific", subQueries: [originalQuery] };
|
|
19039
|
+
}
|
|
19040
|
+
return { mode, subQueries };
|
|
19041
|
+
}
|
|
19042
|
+
|
|
18942
19043
|
// src/lib/memory/mmr.ts
|
|
18943
19044
|
function applyMMR(candidates, k, lambda = 0.5) {
|
|
18944
19045
|
if (candidates.length === 0 || k <= 0) return [];
|
|
@@ -19316,91 +19417,6 @@ function scoreBM25(query, items) {
|
|
|
19316
19417
|
return scoreBM25Prepared(query, prepareBM25Corpus(items));
|
|
19317
19418
|
}
|
|
19318
19419
|
|
|
19319
|
-
// src/lib/memoryVault/decomposeQuery.ts
|
|
19320
|
-
var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
|
|
19321
|
-
var MAX_SUB_QUERIES = 5;
|
|
19322
|
-
var SYSTEM_PROMPT = `You classify a memory query and, if needed, decompose it into concrete sub-queries.
|
|
19323
|
-
|
|
19324
|
-
CLASSIFICATION RULES \u2014 be strict:
|
|
19325
|
-
- "specific": asks for one fact OR a list of items in ONE category (one dimension).
|
|
19326
|
-
Examples: a name, a date, a preference, a location, an ID, a value, "what hobbies",
|
|
19327
|
-
"which conferences", "what open source projects", "what does X do for exercise".
|
|
19328
|
-
Even when the answer is a list, if all items belong to one dimension, it is specific.
|
|
19329
|
-
- "composite": asks about a person, system, or setup MULTI-DIMENSIONALLY \u2014 a summary,
|
|
19330
|
-
an overview, a profile, "tell me about X", "what is my X setup", "describe the team's
|
|
19331
|
-
X". The answer must span multiple distinct fact dimensions (e.g. for a "tech stack":
|
|
19332
|
-
language + database + framework + tools \u2014 four different dimensions).
|
|
19333
|
-
|
|
19334
|
-
When in doubt, prefer "specific". Mis-classifying a single-dimension list as composite
|
|
19335
|
-
hurts retrieval more than the reverse.
|
|
19336
|
-
|
|
19337
|
-
SUB-QUERY RULES (composite only, 3\u20135 questions):
|
|
19338
|
-
- Each sub-query targets a DIFFERENT fact dimension.
|
|
19339
|
-
- Use SHORT parenthetical examples \u2014 2\u20134 concrete options that anchor the
|
|
19340
|
-
embedding to likely memory content. Examples must be terms a user would
|
|
19341
|
-
actually have in their notes (e.g., "Postgres" not "PostgreSQL 15.2 with
|
|
19342
|
-
read replicas"). No verbose qualifiers like "and versions" or "and any
|
|
19343
|
-
relevant configuration details".
|
|
19344
|
-
- 8\u201314 words including the parenthetical. Like a human asking a follow-up.
|
|
19345
|
-
|
|
19346
|
-
Examples:
|
|
19347
|
-
"What is my dog's name?" \u2192 {"mode":"specific","subQueries":["What is my dog's name?"]}
|
|
19348
|
-
"What does the user do for exercise?" \u2192 {"mode":"specific","subQueries":["What does the user do for exercise?"]}
|
|
19349
|
-
"What conferences has the user attended?" \u2192 {"mode":"specific","subQueries":["What conferences has the user attended?"]}
|
|
19350
|
-
"What did I do last Tuesday?" \u2192 {"mode":"specific","subQueries":["What did I do last Tuesday?"]}
|
|
19351
|
-
"Tell me about the user as a person" \u2192 {"mode":"composite","subQueries":["What is the user's name?","Where does the user live?","What does the user do for work?","Any health conditions or allergies?","What are the user's hobbies (sports, music, games)?"]}
|
|
19352
|
-
"What is the user's tech stack?" \u2192 {"mode":"composite","subQueries":["What programming languages does the user use (Python, Go, TypeScript)?","What database does the user use (Postgres, MySQL, Mongo)?","What framework or ORM (React, Django, Prisma)?","What infrastructure (AWS, Docker, K8s)?","What testing tools (Jest, pytest, Cypress)?"]}
|
|
19353
|
-
"Describe the user's development environment" \u2192 {"mode":"composite","subQueries":["What operating system does the user use (macOS, Linux, Windows)?","What editor or IDE (VS Code, Vim, IntelliJ)?","What shell or terminal setup (zsh, bash, tmux)?","What keyboard or display setup (mechanical, vertical monitor)?","Any UI preferences (dark mode, font, vim keybindings)?"]}
|
|
19354
|
-
|
|
19355
|
-
Output strict JSON. No prose.`;
|
|
19356
|
-
async function decomposeQuery(query, options) {
|
|
19357
|
-
const fallback = { mode: "specific", subQueries: [query] };
|
|
19358
|
-
const trimmed = query.trim();
|
|
19359
|
-
if (trimmed.length === 0) return fallback;
|
|
19360
|
-
let parsed;
|
|
19361
|
-
try {
|
|
19362
|
-
parsed = await callPortalJsonCompletion({
|
|
19363
|
-
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
19364
|
-
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
19365
|
-
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
19366
|
-
model: options.model ?? DEFAULT_MODEL,
|
|
19367
|
-
systemPrompt: SYSTEM_PROMPT,
|
|
19368
|
-
// Wrap the bare query in a task framing so the model treats it as
|
|
19369
|
-
// input to classify, not as a question to answer conversationally.
|
|
19370
|
-
// Bare-query inputs caused Anthropic models to respond with prose
|
|
19371
|
-
// like "Do you mean...?" before this wrap.
|
|
19372
|
-
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.
|
|
19373
|
-
|
|
19374
|
-
Query: ${trimmed}`,
|
|
19375
|
-
// Decompose runs on the recall hot path — tighter than the
|
|
19376
|
-
// portalLlm default (consolidate/extract can wait longer).
|
|
19377
|
-
timeoutMs: 2e4,
|
|
19378
|
-
// No internal retry: a failure degrades to the safe `{specific,[query]}`
|
|
19379
|
-
// fallback below, so retrying would only add latency on the hot path.
|
|
19380
|
-
maxAttempts: 1,
|
|
19381
|
-
tag: "memory/decompose",
|
|
19382
|
-
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
19383
|
-
});
|
|
19384
|
-
} catch (err) {
|
|
19385
|
-
getLogger().warn("memoryVault/decompose: portal call failed, falling back to specific", err);
|
|
19386
|
-
return fallback;
|
|
19387
|
-
}
|
|
19388
|
-
if (parsed === null) return fallback;
|
|
19389
|
-
return validate(parsed, trimmed) ?? fallback;
|
|
19390
|
-
}
|
|
19391
|
-
function validate(parsed, originalQuery) {
|
|
19392
|
-
if (typeof parsed !== "object" || parsed === null) return null;
|
|
19393
|
-
const obj = parsed;
|
|
19394
|
-
const mode = obj.mode === "composite" ? "composite" : "specific";
|
|
19395
|
-
if (!Array.isArray(obj.subQueries)) return null;
|
|
19396
|
-
const subQueries = obj.subQueries.filter((s) => typeof s === "string").map((s) => s.trim()).filter((s) => s.length > 0).slice(0, MAX_SUB_QUERIES);
|
|
19397
|
-
if (subQueries.length === 0) return null;
|
|
19398
|
-
if (mode === "specific") {
|
|
19399
|
-
return { mode: "specific", subQueries: [originalQuery] };
|
|
19400
|
-
}
|
|
19401
|
-
return { mode, subQueries };
|
|
19402
|
-
}
|
|
19403
|
-
|
|
19404
19420
|
// src/lib/memoryVault/lruCache.ts
|
|
19405
19421
|
var DEFAULT_VAULT_CACHE_SIZE = 5e3;
|
|
19406
19422
|
var LRUCache = class extends Map {
|
|
@@ -19434,6 +19450,7 @@ function createVaultEmbeddingCache(maxSize = DEFAULT_VAULT_CACHE_SIZE) {
|
|
|
19434
19450
|
}
|
|
19435
19451
|
|
|
19436
19452
|
// src/lib/memoryVault/searchTool.ts
|
|
19453
|
+
var warnedProgrammaticDecomposeIgnored = false;
|
|
19437
19454
|
function normalizeEventTimeKind(kind) {
|
|
19438
19455
|
return kind === "point" || kind === "range" || kind === "ongoing" ? kind : null;
|
|
19439
19456
|
}
|
|
@@ -20368,52 +20385,51 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
20368
20385
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
20369
20386
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
20370
20387
|
};
|
|
20371
|
-
|
|
20372
|
-
|
|
20373
|
-
|
|
20374
|
-
|
|
20375
|
-
|
|
20376
|
-
|
|
20377
|
-
|
|
20378
|
-
|
|
20379
|
-
|
|
20380
|
-
|
|
20381
|
-
|
|
20382
|
-
|
|
20383
|
-
|
|
20384
|
-
|
|
20385
|
-
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20389
|
-
|
|
20390
|
-
|
|
20391
|
-
|
|
20392
|
-
|
|
20393
|
-
|
|
20394
|
-
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20398
|
-
|
|
20399
|
-
|
|
20400
|
-
|
|
20401
|
-
|
|
20402
|
-
|
|
20403
|
-
|
|
20404
|
-
|
|
20405
|
-
|
|
20406
|
-
|
|
20407
|
-
|
|
20408
|
-
|
|
20409
|
-
|
|
20410
|
-
|
|
20411
|
-
|
|
20412
|
-
|
|
20413
|
-
|
|
20414
|
-
|
|
20415
|
-
|
|
20416
|
-
}
|
|
20388
|
+
const normalizedFacets = normalizeSubQueries(searchOptions?.subQueries);
|
|
20389
|
+
const facetQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
20390
|
+
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
20391
|
+
let subEmbeddings;
|
|
20392
|
+
try {
|
|
20393
|
+
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
20394
|
+
} catch (err) {
|
|
20395
|
+
getLogger().warn(
|
|
20396
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
20397
|
+
);
|
|
20398
|
+
subEmbeddings = [];
|
|
20399
|
+
}
|
|
20400
|
+
const subEmbeddingsUsable = facetQueries.length > 0 && subEmbeddings.length === facetQueries.length && subEmbeddings.every((v) => v.length > 0 && v.length === queryEmbedding.length);
|
|
20401
|
+
if (subEmbeddings.length > 0 && !subEmbeddingsUsable) {
|
|
20402
|
+
getLogger().warn(
|
|
20403
|
+
`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`
|
|
20404
|
+
);
|
|
20405
|
+
}
|
|
20406
|
+
if (subEmbeddingsUsable) {
|
|
20407
|
+
const subQueries = facetQueries.map((sq, i) => ({
|
|
20408
|
+
query: sq,
|
|
20409
|
+
embedding: subEmbeddings[i]
|
|
20410
|
+
}));
|
|
20411
|
+
const v2HeadStats = { hadResults: false };
|
|
20412
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
20413
|
+
limit,
|
|
20414
|
+
minSimilarity,
|
|
20415
|
+
rerank: !!searchOptions?.rerank,
|
|
20416
|
+
...searchOptions?.rerankTopN !== void 0 && {
|
|
20417
|
+
rerankTopN: searchOptions.rerankTopN
|
|
20418
|
+
},
|
|
20419
|
+
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
20420
|
+
...searchOptions?.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
20421
|
+
...tuning,
|
|
20422
|
+
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
20423
|
+
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
20424
|
+
rerankStats,
|
|
20425
|
+
v2HeadStats
|
|
20426
|
+
});
|
|
20427
|
+
return stampTimestamps({
|
|
20428
|
+
results: composite,
|
|
20429
|
+
vaultSize,
|
|
20430
|
+
reranked: rerankStats.applied,
|
|
20431
|
+
hadV2Head: v2HeadStats.hadResults
|
|
20432
|
+
});
|
|
20417
20433
|
}
|
|
20418
20434
|
}
|
|
20419
20435
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -20473,6 +20489,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
20473
20489
|
rankedOnCosine: false
|
|
20474
20490
|
};
|
|
20475
20491
|
}
|
|
20492
|
+
if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
|
|
20493
|
+
warnedProgrammaticDecomposeIgnored = true;
|
|
20494
|
+
getLogger().warn(
|
|
20495
|
+
'memoryVault: decompose:"llm" is ignored by searchVaultMemories \u2014 pass subQueries or use createMemoryVaultSearchTool / createRecallTool (719/B4)'
|
|
20496
|
+
);
|
|
20497
|
+
}
|
|
20476
20498
|
const prepared = await prepareVaultCandidates(
|
|
20477
20499
|
query,
|
|
20478
20500
|
vaultCtx,
|
|
@@ -20578,7 +20600,8 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
20578
20600
|
return "Error: A search query is required.";
|
|
20579
20601
|
}
|
|
20580
20602
|
try {
|
|
20581
|
-
const
|
|
20603
|
+
const wantsDecompose = searchOptions?.decompose === "llm" && !!searchOptions.decomposeOptions;
|
|
20604
|
+
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
20582
20605
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
20583
20606
|
if (searchOptions?.useFusion === false) {
|
|
20584
20607
|
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
@@ -20602,7 +20625,14 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
20602
20625
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
20603
20626
|
);
|
|
20604
20627
|
}
|
|
20605
|
-
|
|
20628
|
+
let subQueries;
|
|
20629
|
+
if (wantsDecompose && searchOptions?.decomposeOptions) {
|
|
20630
|
+
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
20631
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
20632
|
+
subQueries = decomp.subQueries;
|
|
20633
|
+
}
|
|
20634
|
+
}
|
|
20635
|
+
const { recall: recall2 } = await import("./recall-74L75BJ3.mjs");
|
|
20606
20636
|
let recallDegraded = [];
|
|
20607
20637
|
const result = await recall2(
|
|
20608
20638
|
query,
|
|
@@ -20618,9 +20648,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
20618
20648
|
...tuningForward,
|
|
20619
20649
|
...folderId !== void 0 && { folderId },
|
|
20620
20650
|
...searchOptions?.scopes && { scopes: searchOptions.scopes },
|
|
20621
|
-
...
|
|
20622
|
-
decomposeOptions: searchOptions.decomposeOptions
|
|
20623
|
-
}
|
|
20651
|
+
...subQueries && { subQueries }
|
|
20624
20652
|
}
|
|
20625
20653
|
);
|
|
20626
20654
|
if (result.vaultSize === 0) {
|
|
@@ -21148,12 +21176,12 @@ var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
|
21148
21176
|
function flagsForBudget(budget) {
|
|
21149
21177
|
switch (budget) {
|
|
21150
21178
|
case "high":
|
|
21151
|
-
return { rerank: true,
|
|
21179
|
+
return { rerank: true, traverse: true };
|
|
21152
21180
|
case "mid":
|
|
21153
|
-
return { rerank: true,
|
|
21181
|
+
return { rerank: true, traverse: false };
|
|
21154
21182
|
case "low":
|
|
21155
21183
|
default:
|
|
21156
|
-
return { rerank: false,
|
|
21184
|
+
return { rerank: false, traverse: false };
|
|
21157
21185
|
}
|
|
21158
21186
|
}
|
|
21159
21187
|
function dedupeBy(items, ...keys) {
|
|
@@ -21172,10 +21200,10 @@ function dedupeBy(items, ...keys) {
|
|
|
21172
21200
|
async function recall(query, ctx, options = {}) {
|
|
21173
21201
|
const types = options.types ?? ["fact"];
|
|
21174
21202
|
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
21175
|
-
const
|
|
21176
|
-
const flags = flagsForBudget(
|
|
21177
|
-
const
|
|
21178
|
-
const
|
|
21203
|
+
const usedBudget = options.budget ?? DEFAULT_BUDGET;
|
|
21204
|
+
const flags = flagsForBudget(usedBudget);
|
|
21205
|
+
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
21206
|
+
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
21179
21207
|
const t0 = nowMs();
|
|
21180
21208
|
let prepMs = 0;
|
|
21181
21209
|
let factLaneMs = 0;
|
|
@@ -21196,7 +21224,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
21196
21224
|
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
21197
21225
|
degraded.push("rerank-unavailable");
|
|
21198
21226
|
}
|
|
21199
|
-
if (
|
|
21227
|
+
if (usedBudget === "high" && options.decomposeOptions && !subQueries && !options.graphRefine) {
|
|
21228
|
+
degraded.push("decompose-moved");
|
|
21229
|
+
}
|
|
21200
21230
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
21201
21231
|
const diagnostics = {
|
|
21202
21232
|
usedBudget,
|
|
@@ -21309,10 +21339,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
21309
21339
|
},
|
|
21310
21340
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
21311
21341
|
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
21312
|
-
|
|
21313
|
-
|
|
21314
|
-
decomposeOptions: options.decomposeOptions
|
|
21315
|
-
},
|
|
21342
|
+
// 719/B4 — composite facets arrive pre-built; no LLM call here.
|
|
21343
|
+
...subQueries && { subQueries },
|
|
21316
21344
|
...options.scopes && { scopes: options.scopes },
|
|
21317
21345
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
21318
21346
|
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
@@ -21660,6 +21688,7 @@ export {
|
|
|
21660
21688
|
EMBEDDINGS_DEGRADED_EMPTY,
|
|
21661
21689
|
RerankerUnavailableError,
|
|
21662
21690
|
isRerankerAvailable,
|
|
21691
|
+
decomposeQuery,
|
|
21663
21692
|
MAX_HOPS,
|
|
21664
21693
|
ENTITY_FANOUT,
|
|
21665
21694
|
NODE_BUDGET,
|