@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
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) {
|
|
@@ -23590,7 +23629,7 @@ __decorateClass([
|
|
|
23590
23629
|
], VaultFolder.prototype, "context", 2);
|
|
23591
23630
|
|
|
23592
23631
|
// src/lib/db/schema.ts
|
|
23593
|
-
var SDK_SCHEMA_VERSION =
|
|
23632
|
+
var SDK_SCHEMA_VERSION = 43;
|
|
23594
23633
|
var sdkSchema = (0, import_watermelondb20.appSchema)({
|
|
23595
23634
|
version: SDK_SCHEMA_VERSION,
|
|
23596
23635
|
tables: [
|
|
@@ -23638,7 +23677,16 @@ var sdkSchema = (0, import_watermelondb20.appSchema)({
|
|
|
23638
23677
|
{ name: "conversation_id", type: "string", isIndexed: true },
|
|
23639
23678
|
{ name: "title", type: "string" },
|
|
23640
23679
|
{ name: "project_id", type: "string", isOptional: true, isIndexed: true },
|
|
23641
|
-
|
|
23680
|
+
// Indexed to match every other list-sorted created_at in this schema.
|
|
23681
|
+
// Note this single-column index is NOT what makes the conversation list
|
|
23682
|
+
// reads fast on native SQLite — they all filter is_deleted as well, and
|
|
23683
|
+
// SQLite will not combine the two indexes, so the composite created by
|
|
23684
|
+
// the v42 migration is what its planner actually uses. This declaration
|
|
23685
|
+
// still earns its keep on the other two adapters: LokiJS builds its
|
|
23686
|
+
// binary indices from `isIndexed` (and ignores `sql` migration steps
|
|
23687
|
+
// outright), and Postgres gathers statistics via autovacuum, so its
|
|
23688
|
+
// planner can use a single-column index the SQLite planner skips.
|
|
23689
|
+
{ name: "created_at", type: "number", isIndexed: true },
|
|
23642
23690
|
{ name: "updated_at", type: "number" },
|
|
23643
23691
|
{ name: "is_deleted", type: "boolean", isIndexed: true },
|
|
23644
23692
|
{ name: "pinned_at", type: "number", isOptional: true }
|
|
@@ -24505,6 +24553,49 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
|
|
|
24505
24553
|
]
|
|
24506
24554
|
})
|
|
24507
24555
|
]
|
|
24556
|
+
},
|
|
24557
|
+
// v42 -> v43: Give the conversation list reads an index they can actually
|
|
24558
|
+
// sort on. All five of them (getConversationsOp, getConversationsLazyOp,
|
|
24559
|
+
// getConversationsByProjectOp, getConversationsByProjectLazyOp and the
|
|
24560
|
+
// keyset getConversationsPageOp) emit `where is_deleted is 0 ... order by
|
|
24561
|
+
// created_at desc`, so before this they resolved is_deleted through its
|
|
24562
|
+
// index and then built a temp B-tree over every live row just to return
|
|
24563
|
+
// the newest page.
|
|
24564
|
+
//
|
|
24565
|
+
// The index is COMPOSITE, and that is the whole point — a bare index on
|
|
24566
|
+
// created_at does not fix this. SQLite will not combine two single-column
|
|
24567
|
+
// indexes here, so with `is_deleted` indexed and `created_at` indexed
|
|
24568
|
+
// separately it still picks conversations_is_deleted and still temp-sorts.
|
|
24569
|
+
// It only prefers a lone created_at index once ANALYZE has populated
|
|
24570
|
+
// sqlite_stat1, and nothing ever runs ANALYZE: not WatermelonDB, not its
|
|
24571
|
+
// native SQLite bindings, not this SDK. Every device is permanently in the
|
|
24572
|
+
// no-statistics state, so the index has to satisfy the filter and the sort
|
|
24573
|
+
// in one structure. `(is_deleted, created_at)` does: equality on the
|
|
24574
|
+
// leading column, ordered scan on the second, and the keyset boundary
|
|
24575
|
+
// becomes a range seek on the same index.
|
|
24576
|
+
//
|
|
24577
|
+
// unsafeExecuteSql, not addColumns: both columns already exist and
|
|
24578
|
+
// WatermelonDB has no add-index migration step, so raw SQL is the only way
|
|
24579
|
+
// to build one in place (same shape as the v19 -> v20 memory_vault
|
|
24580
|
+
// migration). IF NOT EXISTS keeps the step idempotent.
|
|
24581
|
+
//
|
|
24582
|
+
// Two limits worth knowing before someone re-measures this and finds it
|
|
24583
|
+
// missing. First, the LokiJS (web) adapter discards `sql` steps entirely,
|
|
24584
|
+
// so existing browser databases gain nothing — web's only lever is the
|
|
24585
|
+
// `isIndexed` flag on the column itself. Second, this index reaches
|
|
24586
|
+
// MIGRATED databases only: WatermelonDB builds a fresh database purely from
|
|
24587
|
+
// the encoded schema, and its schema format cannot express a composite
|
|
24588
|
+
// index. The one hook that could (`unsafeSql` on the table) is a function,
|
|
24589
|
+
// and the LokiJS adapter posts the schema to its worker, so attaching it
|
|
24590
|
+
// makes the whole schema fail structuredClone and takes the database down
|
|
24591
|
+
// at setup for anyone on `useWebWorker: true`. Not worth it for an index.
|
|
24592
|
+
{
|
|
24593
|
+
toVersion: 43,
|
|
24594
|
+
steps: [
|
|
24595
|
+
(0, import_migrations2.unsafeExecuteSql)(
|
|
24596
|
+
"CREATE INDEX IF NOT EXISTS conversations_is_deleted_created_at ON conversations (is_deleted, created_at);"
|
|
24597
|
+
)
|
|
24598
|
+
]
|
|
24508
24599
|
}
|
|
24509
24600
|
]
|
|
24510
24601
|
});
|
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 & {
|
|
@@ -10343,8 +10393,12 @@ declare class WatermelonChatStorageAdapter implements ChatStorageAdapter {
|
|
|
10343
10393
|
* `topics_updated_at` is a SECOND timestamp because every topic writer pins
|
|
10344
10394
|
* `updated_at` on purpose (recall's recency multiplier) and both sync paths
|
|
10345
10395
|
* key on `updated_at`, so a topic-only change would neither upload nor merge
|
|
10396
|
+
* - v43: Added a (is_deleted, created_at) index to conversations. Every
|
|
10397
|
+
* conversation list read filters is_deleted and orders by created_at DESC,
|
|
10398
|
+
* which previously meant a temp B-tree sort of the whole live set on every
|
|
10399
|
+
* read. Structural only — no column added, no data rewritten
|
|
10346
10400
|
*/
|
|
10347
|
-
declare const SDK_SCHEMA_VERSION =
|
|
10401
|
+
declare const SDK_SCHEMA_VERSION = 43;
|
|
10348
10402
|
/**
|
|
10349
10403
|
* Combined WatermelonDB schema for all SDK storage modules.
|
|
10350
10404
|
*
|
|
@@ -10431,6 +10485,7 @@ declare const sdkSchema: Readonly<{
|
|
|
10431
10485
|
* - v39 → v40: Added `fact_type`, `archived_at`, `trust_tier` columns to memory_vault for typed memory + decay + Tier-0 security (all nullable + plaintext, NULL backfill)
|
|
10432
10486
|
* - v40 → v41: Added `visibility`, `twin_opt_in`, `published_at`, `geohash` columns to memory_vault for the People Nearby cross-user visibility axis (two-tier `private | public`; null/unknown grandfathered as 'private')
|
|
10433
10487
|
* - v41 → v42: Added `topics` + `topics_updated_at` columns to memory_vault, making a memory's topics the durable synced record and `entity`/`memory_entity` a device-local index over it (null `topics` = pre-v42, backfilled from the row's current links by the sweep)
|
|
10488
|
+
* - v42 → v43: Added a composite `(is_deleted, created_at)` index to conversations so the list reads stop temp-sorting (structural only, no data rewritten)
|
|
10434
10489
|
*/
|
|
10435
10490
|
declare const sdkMigrations: Readonly<{
|
|
10436
10491
|
validated: true;
|