@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/expo/index.cjs
CHANGED
|
@@ -6401,11 +6401,11 @@ async function decomposeQuery(query, options) {
|
|
|
6401
6401
|
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.
|
|
6402
6402
|
|
|
6403
6403
|
Query: ${trimmed}`,
|
|
6404
|
-
// Decompose runs
|
|
6404
|
+
// Decompose runs ahead of recall in the tool layer — tighter than the
|
|
6405
6405
|
// portalLlm default (consolidate/extract can wait longer).
|
|
6406
6406
|
timeoutMs: 2e4,
|
|
6407
6407
|
// No internal retry: a failure degrades to the safe `{specific,[query]}`
|
|
6408
|
-
// fallback below
|
|
6408
|
+
// fallback below. The agent/tool loop is the retry surface (719/B4).
|
|
6409
6409
|
maxAttempts: 1,
|
|
6410
6410
|
tag: "memory/decompose",
|
|
6411
6411
|
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
@@ -6417,12 +6417,28 @@ Query: ${trimmed}`,
|
|
|
6417
6417
|
if (parsed === null) return fallback;
|
|
6418
6418
|
return validate(parsed, trimmed) ?? fallback;
|
|
6419
6419
|
}
|
|
6420
|
+
function normalizeSubQueries(raw) {
|
|
6421
|
+
if (!raw || raw.length === 0) return [];
|
|
6422
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6423
|
+
const out = [];
|
|
6424
|
+
for (const s of raw) {
|
|
6425
|
+
if (typeof s !== "string") continue;
|
|
6426
|
+
const t = s.trim();
|
|
6427
|
+
if (t.length === 0) continue;
|
|
6428
|
+
const key = t.toLowerCase();
|
|
6429
|
+
if (seen.has(key)) continue;
|
|
6430
|
+
seen.add(key);
|
|
6431
|
+
out.push(t);
|
|
6432
|
+
if (out.length >= MAX_SUB_QUERIES) break;
|
|
6433
|
+
}
|
|
6434
|
+
return out;
|
|
6435
|
+
}
|
|
6420
6436
|
function validate(parsed, originalQuery) {
|
|
6421
6437
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
6422
6438
|
const obj = parsed;
|
|
6423
6439
|
const mode = obj.mode === "composite" ? "composite" : "specific";
|
|
6424
6440
|
if (!Array.isArray(obj.subQueries)) return null;
|
|
6425
|
-
const subQueries = obj.subQueries
|
|
6441
|
+
const subQueries = normalizeSubQueries(obj.subQueries);
|
|
6426
6442
|
if (subQueries.length === 0) return null;
|
|
6427
6443
|
if (mode === "specific") {
|
|
6428
6444
|
return { mode: "specific", subQueries: [originalQuery] };
|
|
@@ -7039,12 +7055,12 @@ __export(recall_exports, {
|
|
|
7039
7055
|
function flagsForBudget(budget) {
|
|
7040
7056
|
switch (budget) {
|
|
7041
7057
|
case "high":
|
|
7042
|
-
return { rerank: true,
|
|
7058
|
+
return { rerank: true, traverse: true };
|
|
7043
7059
|
case "mid":
|
|
7044
|
-
return { rerank: true,
|
|
7060
|
+
return { rerank: true, traverse: false };
|
|
7045
7061
|
case "low":
|
|
7046
7062
|
default:
|
|
7047
|
-
return { rerank: false,
|
|
7063
|
+
return { rerank: false, traverse: false };
|
|
7048
7064
|
}
|
|
7049
7065
|
}
|
|
7050
7066
|
function dedupeBy(items, ...keys) {
|
|
@@ -7063,10 +7079,10 @@ function dedupeBy(items, ...keys) {
|
|
|
7063
7079
|
async function recall(query, ctx, options = {}) {
|
|
7064
7080
|
const types = options.types ?? ["fact"];
|
|
7065
7081
|
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
7066
|
-
const
|
|
7067
|
-
const flags = flagsForBudget(
|
|
7068
|
-
const
|
|
7069
|
-
const
|
|
7082
|
+
const usedBudget = options.budget ?? DEFAULT_BUDGET;
|
|
7083
|
+
const flags = flagsForBudget(usedBudget);
|
|
7084
|
+
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
7085
|
+
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
7070
7086
|
const t0 = nowMs();
|
|
7071
7087
|
let prepMs = 0;
|
|
7072
7088
|
let factLaneMs = 0;
|
|
@@ -7087,7 +7103,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
7087
7103
|
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
7088
7104
|
degraded.push("rerank-unavailable");
|
|
7089
7105
|
}
|
|
7090
|
-
if (
|
|
7106
|
+
if (usedBudget === "high" && options.decomposeOptions && !subQueries && !options.graphRefine) {
|
|
7107
|
+
degraded.push("decompose-moved");
|
|
7108
|
+
}
|
|
7091
7109
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
7092
7110
|
const diagnostics = {
|
|
7093
7111
|
usedBudget,
|
|
@@ -7200,10 +7218,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
7200
7218
|
},
|
|
7201
7219
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
7202
7220
|
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
decomposeOptions: options.decomposeOptions
|
|
7206
|
-
},
|
|
7221
|
+
// 719/B4 — composite facets arrive pre-built; no LLM call here.
|
|
7222
|
+
...subQueries && { subQueries },
|
|
7207
7223
|
...options.scopes && { scopes: options.scopes },
|
|
7208
7224
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
7209
7225
|
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
@@ -7440,6 +7456,7 @@ var init_recall = __esm({
|
|
|
7440
7456
|
init_logger();
|
|
7441
7457
|
init_constants();
|
|
7442
7458
|
init_embeddings();
|
|
7459
|
+
init_decomposeQuery();
|
|
7443
7460
|
init_searchTool();
|
|
7444
7461
|
init_graphTraversal();
|
|
7445
7462
|
init_observationTrend();
|
|
@@ -8385,52 +8402,51 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
8385
8402
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
8386
8403
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
8387
8404
|
};
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
}
|
|
8405
|
+
const normalizedFacets = normalizeSubQueries(searchOptions?.subQueries);
|
|
8406
|
+
const facetQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
8407
|
+
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
8408
|
+
let subEmbeddings;
|
|
8409
|
+
try {
|
|
8410
|
+
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
8411
|
+
} catch (err) {
|
|
8412
|
+
getLogger().warn(
|
|
8413
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
8414
|
+
);
|
|
8415
|
+
subEmbeddings = [];
|
|
8416
|
+
}
|
|
8417
|
+
const subEmbeddingsUsable = facetQueries.length > 0 && subEmbeddings.length === facetQueries.length && subEmbeddings.every((v) => v.length > 0 && v.length === queryEmbedding.length);
|
|
8418
|
+
if (subEmbeddings.length > 0 && !subEmbeddingsUsable) {
|
|
8419
|
+
getLogger().warn(
|
|
8420
|
+
`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`
|
|
8421
|
+
);
|
|
8422
|
+
}
|
|
8423
|
+
if (subEmbeddingsUsable) {
|
|
8424
|
+
const subQueries = facetQueries.map((sq, i) => ({
|
|
8425
|
+
query: sq,
|
|
8426
|
+
embedding: subEmbeddings[i]
|
|
8427
|
+
}));
|
|
8428
|
+
const v2HeadStats = { hadResults: false };
|
|
8429
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
8430
|
+
limit,
|
|
8431
|
+
minSimilarity,
|
|
8432
|
+
rerank: !!searchOptions?.rerank,
|
|
8433
|
+
...searchOptions?.rerankTopN !== void 0 && {
|
|
8434
|
+
rerankTopN: searchOptions.rerankTopN
|
|
8435
|
+
},
|
|
8436
|
+
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
8437
|
+
...searchOptions?.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
8438
|
+
...tuning,
|
|
8439
|
+
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
8440
|
+
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
8441
|
+
rerankStats,
|
|
8442
|
+
v2HeadStats
|
|
8443
|
+
});
|
|
8444
|
+
return stampTimestamps({
|
|
8445
|
+
results: composite,
|
|
8446
|
+
vaultSize,
|
|
8447
|
+
reranked: rerankStats.applied,
|
|
8448
|
+
hadV2Head: v2HeadStats.hadResults
|
|
8449
|
+
});
|
|
8434
8450
|
}
|
|
8435
8451
|
}
|
|
8436
8452
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -8490,6 +8506,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
8490
8506
|
rankedOnCosine: false
|
|
8491
8507
|
};
|
|
8492
8508
|
}
|
|
8509
|
+
if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
|
|
8510
|
+
warnedProgrammaticDecomposeIgnored = true;
|
|
8511
|
+
getLogger().warn(
|
|
8512
|
+
'memoryVault: decompose:"llm" is ignored by searchVaultMemories \u2014 pass subQueries or use createMemoryVaultSearchTool / createRecallTool (719/B4)'
|
|
8513
|
+
);
|
|
8514
|
+
}
|
|
8493
8515
|
const prepared = await prepareVaultCandidates(
|
|
8494
8516
|
query,
|
|
8495
8517
|
vaultCtx,
|
|
@@ -8594,7 +8616,8 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8594
8616
|
return "Error: A search query is required.";
|
|
8595
8617
|
}
|
|
8596
8618
|
try {
|
|
8597
|
-
const
|
|
8619
|
+
const wantsDecompose = searchOptions?.decompose === "llm" && !!searchOptions.decomposeOptions;
|
|
8620
|
+
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
8598
8621
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
8599
8622
|
if (searchOptions?.useFusion === false) {
|
|
8600
8623
|
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
@@ -8618,6 +8641,13 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8618
8641
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
8619
8642
|
);
|
|
8620
8643
|
}
|
|
8644
|
+
let subQueries;
|
|
8645
|
+
if (wantsDecompose && searchOptions?.decomposeOptions) {
|
|
8646
|
+
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
8647
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
8648
|
+
subQueries = decomp.subQueries;
|
|
8649
|
+
}
|
|
8650
|
+
}
|
|
8621
8651
|
const { recall: recall2 } = await Promise.resolve().then(() => (init_recall(), recall_exports));
|
|
8622
8652
|
let recallDegraded = [];
|
|
8623
8653
|
const result = await recall2(
|
|
@@ -8634,9 +8664,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8634
8664
|
...tuningForward,
|
|
8635
8665
|
...folderId !== void 0 && { folderId },
|
|
8636
8666
|
...searchOptions?.scopes && { scopes: searchOptions.scopes },
|
|
8637
|
-
...
|
|
8638
|
-
decomposeOptions: searchOptions.decomposeOptions
|
|
8639
|
-
}
|
|
8667
|
+
...subQueries && { subQueries }
|
|
8640
8668
|
}
|
|
8641
8669
|
);
|
|
8642
8670
|
if (result.vaultSize === 0) {
|
|
@@ -8666,7 +8694,7 @@ ${formatted}`;
|
|
|
8666
8694
|
}
|
|
8667
8695
|
};
|
|
8668
8696
|
}
|
|
8669
|
-
var SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
8697
|
+
var warnedProgrammaticDecomposeIgnored, SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
8670
8698
|
var init_searchTool = __esm({
|
|
8671
8699
|
"src/lib/memoryVault/searchTool.ts"() {
|
|
8672
8700
|
"use strict";
|
|
@@ -8684,6 +8712,7 @@ var init_searchTool = __esm({
|
|
|
8684
8712
|
init_bm25();
|
|
8685
8713
|
init_decomposeQuery();
|
|
8686
8714
|
init_lruCache();
|
|
8715
|
+
warnedProgrammaticDecomposeIgnored = false;
|
|
8687
8716
|
SUPERSESSION_SIMILARITY_THRESHOLD = 0.7;
|
|
8688
8717
|
SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
8689
8718
|
SUPERSESSION_BOOST_FACTOR = 0.8;
|
|
@@ -16715,6 +16744,7 @@ function rankProfileCandidates(inputs, now = Date.now(), options = {}) {
|
|
|
16715
16744
|
init_recall();
|
|
16716
16745
|
|
|
16717
16746
|
// src/lib/memory/recallTool.ts
|
|
16747
|
+
init_decomposeQuery();
|
|
16718
16748
|
init_recall();
|
|
16719
16749
|
init_recallConstants();
|
|
16720
16750
|
var DEFAULT_LIMIT2 = 8;
|
|
@@ -16812,7 +16842,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
16812
16842
|
type: "function",
|
|
16813
16843
|
function: {
|
|
16814
16844
|
name: RECALL_TOOL_NAME,
|
|
16815
|
-
description:
|
|
16845
|
+
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.`,
|
|
16816
16846
|
arguments: {
|
|
16817
16847
|
type: "object",
|
|
16818
16848
|
properties: {
|
|
@@ -16867,6 +16897,13 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
16867
16897
|
let surfaced = 0;
|
|
16868
16898
|
try {
|
|
16869
16899
|
let recallDegraded = [];
|
|
16900
|
+
let subQueries;
|
|
16901
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
16902
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
16903
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
16904
|
+
subQueries = decomp.subQueries;
|
|
16905
|
+
}
|
|
16906
|
+
}
|
|
16870
16907
|
const recallOpts = {
|
|
16871
16908
|
onDiagnostics: (d) => {
|
|
16872
16909
|
recallDegraded = d.degraded;
|
|
@@ -16880,10 +16917,12 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
16880
16917
|
...toolOptions?.excludeConversationId && {
|
|
16881
16918
|
excludeConversationId: toolOptions.excludeConversationId
|
|
16882
16919
|
},
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16920
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
16921
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
16922
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
16923
|
+
// be threaded later when the tool opts into that path.
|
|
16924
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
16925
|
+
...subQueries && { subQueries }
|
|
16887
16926
|
};
|
|
16888
16927
|
const result = await recall(query, ctx, recallOpts);
|
|
16889
16928
|
if (callbacks?.onChunksRetrieved) {
|
|
@@ -21017,7 +21056,7 @@ __decorateClass([
|
|
|
21017
21056
|
], VaultFolder.prototype, "context", 2);
|
|
21018
21057
|
|
|
21019
21058
|
// src/lib/db/schema.ts
|
|
21020
|
-
var SDK_SCHEMA_VERSION =
|
|
21059
|
+
var SDK_SCHEMA_VERSION = 43;
|
|
21021
21060
|
var sdkSchema = (0, import_watermelondb19.appSchema)({
|
|
21022
21061
|
version: SDK_SCHEMA_VERSION,
|
|
21023
21062
|
tables: [
|
|
@@ -21065,7 +21104,16 @@ var sdkSchema = (0, import_watermelondb19.appSchema)({
|
|
|
21065
21104
|
{ name: "conversation_id", type: "string", isIndexed: true },
|
|
21066
21105
|
{ name: "title", type: "string" },
|
|
21067
21106
|
{ name: "project_id", type: "string", isOptional: true, isIndexed: true },
|
|
21068
|
-
|
|
21107
|
+
// Indexed to match every other list-sorted created_at in this schema.
|
|
21108
|
+
// Note this single-column index is NOT what makes the conversation list
|
|
21109
|
+
// reads fast on native SQLite — they all filter is_deleted as well, and
|
|
21110
|
+
// SQLite will not combine the two indexes, so the composite created by
|
|
21111
|
+
// the v42 migration is what its planner actually uses. This declaration
|
|
21112
|
+
// still earns its keep on the other two adapters: LokiJS builds its
|
|
21113
|
+
// binary indices from `isIndexed` (and ignores `sql` migration steps
|
|
21114
|
+
// outright), and Postgres gathers statistics via autovacuum, so its
|
|
21115
|
+
// planner can use a single-column index the SQLite planner skips.
|
|
21116
|
+
{ name: "created_at", type: "number", isIndexed: true },
|
|
21069
21117
|
{ name: "updated_at", type: "number" },
|
|
21070
21118
|
{ name: "is_deleted", type: "boolean", isIndexed: true },
|
|
21071
21119
|
{ name: "pinned_at", type: "number", isOptional: true }
|
|
@@ -21932,6 +21980,49 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
|
|
|
21932
21980
|
]
|
|
21933
21981
|
})
|
|
21934
21982
|
]
|
|
21983
|
+
},
|
|
21984
|
+
// v42 -> v43: Give the conversation list reads an index they can actually
|
|
21985
|
+
// sort on. All five of them (getConversationsOp, getConversationsLazyOp,
|
|
21986
|
+
// getConversationsByProjectOp, getConversationsByProjectLazyOp and the
|
|
21987
|
+
// keyset getConversationsPageOp) emit `where is_deleted is 0 ... order by
|
|
21988
|
+
// created_at desc`, so before this they resolved is_deleted through its
|
|
21989
|
+
// index and then built a temp B-tree over every live row just to return
|
|
21990
|
+
// the newest page.
|
|
21991
|
+
//
|
|
21992
|
+
// The index is COMPOSITE, and that is the whole point — a bare index on
|
|
21993
|
+
// created_at does not fix this. SQLite will not combine two single-column
|
|
21994
|
+
// indexes here, so with `is_deleted` indexed and `created_at` indexed
|
|
21995
|
+
// separately it still picks conversations_is_deleted and still temp-sorts.
|
|
21996
|
+
// It only prefers a lone created_at index once ANALYZE has populated
|
|
21997
|
+
// sqlite_stat1, and nothing ever runs ANALYZE: not WatermelonDB, not its
|
|
21998
|
+
// native SQLite bindings, not this SDK. Every device is permanently in the
|
|
21999
|
+
// no-statistics state, so the index has to satisfy the filter and the sort
|
|
22000
|
+
// in one structure. `(is_deleted, created_at)` does: equality on the
|
|
22001
|
+
// leading column, ordered scan on the second, and the keyset boundary
|
|
22002
|
+
// becomes a range seek on the same index.
|
|
22003
|
+
//
|
|
22004
|
+
// unsafeExecuteSql, not addColumns: both columns already exist and
|
|
22005
|
+
// WatermelonDB has no add-index migration step, so raw SQL is the only way
|
|
22006
|
+
// to build one in place (same shape as the v19 -> v20 memory_vault
|
|
22007
|
+
// migration). IF NOT EXISTS keeps the step idempotent.
|
|
22008
|
+
//
|
|
22009
|
+
// Two limits worth knowing before someone re-measures this and finds it
|
|
22010
|
+
// missing. First, the LokiJS (web) adapter discards `sql` steps entirely,
|
|
22011
|
+
// so existing browser databases gain nothing — web's only lever is the
|
|
22012
|
+
// `isIndexed` flag on the column itself. Second, this index reaches
|
|
22013
|
+
// MIGRATED databases only: WatermelonDB builds a fresh database purely from
|
|
22014
|
+
// the encoded schema, and its schema format cannot express a composite
|
|
22015
|
+
// index. The one hook that could (`unsafeSql` on the table) is a function,
|
|
22016
|
+
// and the LokiJS adapter posts the schema to its worker, so attaching it
|
|
22017
|
+
// makes the whole schema fail structuredClone and takes the database down
|
|
22018
|
+
// at setup for anyone on `useWebWorker: true`. Not worth it for an index.
|
|
22019
|
+
{
|
|
22020
|
+
toVersion: 43,
|
|
22021
|
+
steps: [
|
|
22022
|
+
(0, import_migrations2.unsafeExecuteSql)(
|
|
22023
|
+
"CREATE INDEX IF NOT EXISTS conversations_is_deleted_created_at ON conversations (is_deleted, created_at);"
|
|
22024
|
+
)
|
|
22025
|
+
]
|
|
21935
22026
|
}
|
|
21936
22027
|
]
|
|
21937
22028
|
});
|
package/dist/expo/index.d.mts
CHANGED
|
@@ -5009,15 +5009,26 @@ interface MemoryVaultSearchOptions {
|
|
|
5009
5009
|
/** RRF smoothing constant for lane fusion. Default 60. */
|
|
5010
5010
|
rrfK?: number;
|
|
5011
5011
|
/**
|
|
5012
|
-
*
|
|
5013
|
-
*
|
|
5014
|
-
*
|
|
5015
|
-
*
|
|
5012
|
+
* Pre-decomposed facet queries for the composite ranker (719/B4). When
|
|
5013
|
+
* ≥2 are supplied (and embeddings are available), runs {@link rankComposite}
|
|
5014
|
+
* over them — no LLM call inside the search path. Callers that want LLM
|
|
5015
|
+
* rewrite (e.g. `createRecallTool`) call `decomposeQuery` first and pass
|
|
5016
|
+
* the facets here.
|
|
5017
|
+
*/
|
|
5018
|
+
subQueries?: string[];
|
|
5019
|
+
/**
|
|
5020
|
+
* @deprecated 719/B4 — ignored by {@link searchVaultMemories} /
|
|
5021
|
+
* {@link searchVaultMemoriesWithSize}. Pass {@link MemoryVaultSearchOptions.subQueries}
|
|
5022
|
+
* (or use `createRecallTool`). The legacy {@link createMemoryVaultSearchTool}
|
|
5023
|
+
* executor still honors `decompose: "llm"` + `decomposeOptions` for eval
|
|
5024
|
+
* parity, then forwards facets into the LLM-free search path.
|
|
5016
5025
|
*/
|
|
5017
5026
|
decompose?: "off" | "llm";
|
|
5018
|
-
/**
|
|
5019
|
-
*
|
|
5020
|
-
*
|
|
5027
|
+
/**
|
|
5028
|
+
* @deprecated 719/B4 — see `decompose`. Ignored on the programmatic search
|
|
5029
|
+
* path; tool-layer rewrite still reads this from the search-tool options.
|
|
5030
|
+
* Prefer `RecallToolOptions.decomposeOptions` with `createRecallTool`.
|
|
5031
|
+
*/
|
|
5021
5032
|
decomposeOptions?: PortalLlmAuth & {
|
|
5022
5033
|
baseUrl?: string;
|
|
5023
5034
|
model?: string;
|
|
@@ -5182,9 +5193,11 @@ type MemoryKind = "fact" | "chunk";
|
|
|
5182
5193
|
* Budget controls retrieval depth/cost. Higher budgets enable more
|
|
5183
5194
|
* candidate sources and the cross-encoder reranker.
|
|
5184
5195
|
*
|
|
5185
|
-
* - `low`: cosine + BM25
|
|
5186
|
-
* - `mid`: +
|
|
5187
|
-
* - `high`: +
|
|
5196
|
+
* - `low`: cosine + BM25 + recency. No reranker. Mobile default.
|
|
5197
|
+
* - `mid`: + cross-encoder rerank.
|
|
5198
|
+
* - `high`: + multi-hop graph traversal. LLM-free — query decomposition
|
|
5199
|
+
* (when wanted) lives in the tool/agent layer ({@link createRecallTool}),
|
|
5200
|
+
* not inside `recall()` itself (719/B4).
|
|
5188
5201
|
*/
|
|
5189
5202
|
type Budget = "low" | "mid" | "high";
|
|
5190
5203
|
interface ScoreBreakdown {
|
|
@@ -5284,10 +5297,28 @@ interface RecallOptions {
|
|
|
5284
5297
|
/** Drop results below this score. Default: 0.1 for facts, 0.5 for chunks (mirrors today's defaults). */
|
|
5285
5298
|
minScore?: number;
|
|
5286
5299
|
/**
|
|
5287
|
-
*
|
|
5288
|
-
*
|
|
5289
|
-
*
|
|
5290
|
-
*
|
|
5300
|
+
* Pre-decomposed facet queries for the composite ranker. When ≥2 are
|
|
5301
|
+
* supplied, the vault lane runs `rankComposite` over them (no LLM call
|
|
5302
|
+
* inside `recall()` — 719/B4). Callers that still want LLM rewrite
|
|
5303
|
+
* (e.g. {@link createRecallTool} at `budget: 'high'`) call
|
|
5304
|
+
* `decomposeQuery` themselves and pass the result here. A single entry
|
|
5305
|
+
* (or omitting this) keeps the single-query path.
|
|
5306
|
+
*/
|
|
5307
|
+
subQueries?: string[];
|
|
5308
|
+
/**
|
|
5309
|
+
* Auth + endpoint for optional LLM helpers that reuse portal auth —
|
|
5310
|
+
* currently {@link RecallOptions.graphRefine} neighbor selection.
|
|
5311
|
+
* Query decomposition is **not** driven by this field inside `recall()`
|
|
5312
|
+
* (719/B4); {@link createRecallTool} reads the same shape from
|
|
5313
|
+
* `RecallToolOptions.decomposeOptions` for tool-layer rewrite.
|
|
5314
|
+
*
|
|
5315
|
+
* Callers that still pass `{ budget: 'high', decomposeOptions }` without
|
|
5316
|
+
* {@link RecallOptions.subQueries} keep compiling but no longer rewrite —
|
|
5317
|
+
* `recall()` emits `decompose-moved` on {@link RecallDiagnostics.degraded}
|
|
5318
|
+
* so upgrades without a changelog read still leave a telemetry breadcrumb.
|
|
5319
|
+
*
|
|
5320
|
+
* Auth is the dual pattern — one of `apiKey` / `getToken` is required;
|
|
5321
|
+
* see {@link PortalLlmAuth}.
|
|
5291
5322
|
*/
|
|
5292
5323
|
decomposeOptions?: PortalLlmAuth & {
|
|
5293
5324
|
baseUrl?: string;
|
|
@@ -5391,9 +5422,22 @@ type RecallDegradation =
|
|
|
5391
5422
|
/** Rerank was requested (budget mid/high) but the cross-encoder didn't run
|
|
5392
5423
|
* this call — unavailable (e.g. React Native) or a transient failure. */
|
|
5393
5424
|
"rerank-unavailable"
|
|
5394
|
-
/**
|
|
5395
|
-
*
|
|
5425
|
+
/**
|
|
5426
|
+
* @deprecated 719/B4 moved query decomposition out of `recall()`. Budget
|
|
5427
|
+
* `high` no longer requires `decomposeOptions` and this signal is never
|
|
5428
|
+
* emitted. Prefer `"decompose-moved"` for the upgrade breadcrumb. Kept in
|
|
5429
|
+
* the union so existing telemetry consumers stay typed.
|
|
5430
|
+
*/
|
|
5396
5431
|
| "decompose-unavailable"
|
|
5432
|
+
/**
|
|
5433
|
+
* `budget: 'high'` with `decomposeOptions` set but no usable
|
|
5434
|
+
* {@link RecallOptions.subQueries}. Pre-B4 this call shape triggered LLM
|
|
5435
|
+
* rewrite inside `recall()`; post-B4 it stays on the single-query high
|
|
5436
|
+
* path (rerank + graph) and callers must pass facets (or use
|
|
5437
|
+
* {@link createRecallTool}). Surfaced so silent quality regressions show
|
|
5438
|
+
* up in diagnostics instead of looking healthier than before.
|
|
5439
|
+
*/
|
|
5440
|
+
| "decompose-moved"
|
|
5397
5441
|
/** There was no usable cosine lane, so results were ranked on BM25 (lexical)
|
|
5398
5442
|
* alone: either the query embedding failed (or came back empty), or no
|
|
5399
5443
|
* candidate had a vector to score against it because the row (re)embed failed.
|
|
@@ -7463,9 +7507,14 @@ declare function rankProfileCandidates(inputs: readonly ProfileSalienceInput[],
|
|
|
7463
7507
|
* Unified Recall API — single retrieval surface above vault + engine.
|
|
7464
7508
|
*
|
|
7465
7509
|
* Budget maps to pipeline depth (mirrors Hindsight's tiered defaults):
|
|
7466
|
-
* - `low` → V2 cosine + BM25 + recency (no rerank
|
|
7510
|
+
* - `low` → V2 cosine + BM25 + recency (no rerank)
|
|
7467
7511
|
* - `mid` → V2 + cross-encoder rerank
|
|
7468
|
-
* - `high` → V2 + rerank +
|
|
7512
|
+
* - `high` → V2 + rerank + multi-hop graph traversal
|
|
7513
|
+
*
|
|
7514
|
+
* LLM-free by design (719/B4): query decomposition for composite asks
|
|
7515
|
+
* lives in the tool/agent layer (`createRecallTool`), which may pass
|
|
7516
|
+
* pre-built `subQueries` into this API. `recall()` itself never pays an
|
|
7517
|
+
* LLM RTT.
|
|
7469
7518
|
*
|
|
7470
7519
|
* Fact + chunk lanes are fused with RRF (k=60). The previous naive
|
|
7471
7520
|
* "sort the union by raw score" path is gone — score scales differ
|
|
@@ -7520,7 +7569,8 @@ interface RecallToolOptions {
|
|
|
7520
7569
|
folderId?: string | null;
|
|
7521
7570
|
/** Exclude one conversation from chunk results (typically the active one). */
|
|
7522
7571
|
excludeConversationId?: string;
|
|
7523
|
-
/** LLM-decompose options; only used at budget="high".
|
|
7572
|
+
/** LLM-decompose options; only used at budget="high". Runs in THIS tool
|
|
7573
|
+
* executor (719/B4) — `recall()` itself is LLM-free. Auth follows the
|
|
7524
7574
|
* dual pattern: apiKey (server/CLI) or getToken (browser identity
|
|
7525
7575
|
* tokens) — at least one required. */
|
|
7526
7576
|
decomposeOptions?: PortalLlmAuth & {
|
|
@@ -8729,8 +8779,12 @@ declare function useChatStorage(options: UseChatStorageOptions): UseChatStorageR
|
|
|
8729
8779
|
* `topics_updated_at` is a SECOND timestamp because every topic writer pins
|
|
8730
8780
|
* `updated_at` on purpose (recall's recency multiplier) and both sync paths
|
|
8731
8781
|
* key on `updated_at`, so a topic-only change would neither upload nor merge
|
|
8782
|
+
* - v43: Added a (is_deleted, created_at) index to conversations. Every
|
|
8783
|
+
* conversation list read filters is_deleted and orders by created_at DESC,
|
|
8784
|
+
* which previously meant a temp B-tree sort of the whole live set on every
|
|
8785
|
+
* read. Structural only — no column added, no data rewritten
|
|
8732
8786
|
*/
|
|
8733
|
-
declare const SDK_SCHEMA_VERSION =
|
|
8787
|
+
declare const SDK_SCHEMA_VERSION = 43;
|
|
8734
8788
|
/**
|
|
8735
8789
|
* Combined WatermelonDB schema for all SDK storage modules.
|
|
8736
8790
|
*
|
|
@@ -8817,6 +8871,7 @@ declare const sdkSchema: Readonly<{
|
|
|
8817
8871
|
* - 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)
|
|
8818
8872
|
* - 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')
|
|
8819
8873
|
* - 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)
|
|
8874
|
+
* - v42 → v43: Added a composite `(is_deleted, created_at)` index to conversations so the list reads stop temp-sorting (structural only, no data rewritten)
|
|
8820
8875
|
*/
|
|
8821
8876
|
declare const sdkMigrations: Readonly<{
|
|
8822
8877
|
validated: true;
|