@anuma/sdk 3.2.0 → 3.3.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/client/index.cjs +793 -1420
- package/dist/client/index.d.mts +406 -402
- package/dist/client/index.d.ts +406 -402
- package/dist/client/index.mjs +793 -1420
- package/dist/expo/{chunk-KXIUA7ZV.mjs → chunk-EIHIZ5L4.mjs} +418 -18
- package/dist/expo/index.cjs +1462 -219
- package/dist/expo/index.d.mts +1763 -795
- package/dist/expo/index.d.ts +1763 -795
- package/dist/expo/index.mjs +1006 -190
- package/dist/expo/{recall-3YPU4PS2.mjs → recall-C3LJ5R2E.mjs} +1 -1
- package/dist/index.cjs +453 -783
- package/dist/index.d.mts +491 -487
- package/dist/index.d.ts +491 -487
- package/dist/index.mjs +453 -783
- package/dist/react/{chunk-Y7PMXJT6.mjs → chunk-PWTWECXY.mjs} +419 -18
- package/dist/react/index.cjs +1539 -345
- package/dist/react/index.d.mts +1816 -825
- package/dist/react/index.d.ts +1816 -825
- package/dist/react/index.mjs +1079 -312
- package/dist/react/{recall-GYNSL2DS.mjs → recall-FZVV5XUU.mjs} +1 -1
- package/dist/server/{chunk-Y3ZS4OI3.mjs → chunk-J5QZOPUI.mjs} +418 -18
- package/dist/server/index.cjs +1341 -75
- package/dist/server/index.d.mts +2778 -1810
- package/dist/server/index.d.ts +2778 -1810
- package/dist/server/index.mjs +890 -51
- package/dist/server/{recall-Z72DM2JK.mjs → recall-NNBMWRLB.mjs} +1 -1
- package/dist/tools/selection/index.cjs +3 -0
- package/dist/tools/selection/index.mjs +3 -0
- package/package.json +2 -2
|
@@ -1955,6 +1955,36 @@ async function getMemoriesByEntityNamesOp(ctx, entityNames) {
|
|
|
1955
1955
|
}
|
|
1956
1956
|
return out;
|
|
1957
1957
|
}
|
|
1958
|
+
async function getEntitiesByMemoryIdsOp(ctx, memoryIds) {
|
|
1959
|
+
const unique = Array.from(new Set(memoryIds.filter((id) => id.length > 0)));
|
|
1960
|
+
if (unique.length === 0) return /* @__PURE__ */ new Map();
|
|
1961
|
+
const linkConditions = [Q2.where("memory_id", Q2.oneOf(unique))];
|
|
1962
|
+
if (ctx.userId !== void 0) {
|
|
1963
|
+
if (ctx.allowUnscopedRows) {
|
|
1964
|
+
linkConditions.push(Q2.or(Q2.where("user_id", ctx.userId), Q2.where("user_id", null)));
|
|
1965
|
+
} else {
|
|
1966
|
+
linkConditions.push(Q2.where("user_id", ctx.userId));
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
const links = await ctx.memoryEntityCollection.query(...linkConditions).fetch();
|
|
1970
|
+
if (links.length === 0) return /* @__PURE__ */ new Map();
|
|
1971
|
+
const entityIds = Array.from(new Set(links.map((l) => String(l.entityId))));
|
|
1972
|
+
const entityRows = await ctx.entityCollection.query(Q2.where("id", Q2.oneOf(entityIds))).fetch();
|
|
1973
|
+
const entityIdToName = new Map(entityRows.map((e) => [e.id, e.canonicalName]));
|
|
1974
|
+
const out = /* @__PURE__ */ new Map();
|
|
1975
|
+
for (const link of links) {
|
|
1976
|
+
const entityName = entityIdToName.get(String(link.entityId));
|
|
1977
|
+
if (!entityName) continue;
|
|
1978
|
+
const memoryId = String(link.memoryId);
|
|
1979
|
+
let bucket = out.get(memoryId);
|
|
1980
|
+
if (!bucket) {
|
|
1981
|
+
bucket = /* @__PURE__ */ new Set();
|
|
1982
|
+
out.set(memoryId, bucket);
|
|
1983
|
+
}
|
|
1984
|
+
bucket.add(entityName);
|
|
1985
|
+
}
|
|
1986
|
+
return out;
|
|
1987
|
+
}
|
|
1958
1988
|
|
|
1959
1989
|
// src/lib/db/memoryVault/operations.ts
|
|
1960
1990
|
import { Q as Q3 } from "@nozbe/watermelondb";
|
|
@@ -1992,11 +2022,18 @@ function isOwnedByCtxUser(ctx, record) {
|
|
|
1992
2022
|
function baseVaultConditions(ctx, options) {
|
|
1993
2023
|
return [
|
|
1994
2024
|
...options?.includeDeleted ? [] : [Q3.where("is_deleted", false)],
|
|
2025
|
+
...options?.includeArchived ? [] : [Q3.where("archived_at", Q3.eq(null))],
|
|
2026
|
+
...options?.includeQuarantined ? [] : [Q3.where("trust_tier", Q3.notEq("quarantined"))],
|
|
1995
2027
|
...options?.includeSuperseded ? [] : [Q3.where("superseded_by", null)],
|
|
1996
2028
|
...ctx.userId !== void 0 ? [Q3.where("user_id", ctx.userId)] : [],
|
|
1997
2029
|
...options?.since ? [Q3.where("updated_at", Q3.gt(options.since.getTime()))] : []
|
|
1998
2030
|
];
|
|
1999
2031
|
}
|
|
2032
|
+
var KNOWN_TRUST_TIERS = /* @__PURE__ */ new Set(["quarantined", "trusted"]);
|
|
2033
|
+
function normalizeTrustTier(value) {
|
|
2034
|
+
if (value === void 0 || value === null) return null;
|
|
2035
|
+
return KNOWN_TRUST_TIERS.has(value) ? value : null;
|
|
2036
|
+
}
|
|
2000
2037
|
async function mapInBatches(items, fn) {
|
|
2001
2038
|
const BATCH = 50;
|
|
2002
2039
|
const results = [];
|
|
@@ -2037,6 +2074,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
2037
2074
|
supersededBy: memory.supersededBy ?? null,
|
|
2038
2075
|
supersededAt: memory.supersededAt ?? null,
|
|
2039
2076
|
lastObservedAt: memory.lastObservedAt ?? null,
|
|
2077
|
+
factType: memory.factType ?? null,
|
|
2078
|
+
archivedAt: memory.archivedAt ?? null,
|
|
2079
|
+
trustTier: memory.trustTier ?? null,
|
|
2040
2080
|
createdAt: memory.createdAt,
|
|
2041
2081
|
updatedAt: memory.updatedAt,
|
|
2042
2082
|
isDeleted: memory.isDeleted
|
|
@@ -2078,6 +2118,12 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
2078
2118
|
record._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
2079
2119
|
record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
2080
2120
|
}
|
|
2121
|
+
if (opts.factType !== void 0) {
|
|
2122
|
+
record._setRaw("fact_type", opts.factType);
|
|
2123
|
+
}
|
|
2124
|
+
if (opts.trustTier !== void 0) {
|
|
2125
|
+
record._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
2126
|
+
}
|
|
2081
2127
|
});
|
|
2082
2128
|
});
|
|
2083
2129
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -2218,6 +2264,12 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
2218
2264
|
record._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
2219
2265
|
record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
2220
2266
|
}
|
|
2267
|
+
if (opts.factType !== void 0) {
|
|
2268
|
+
record._setRaw("fact_type", opts.factType);
|
|
2269
|
+
}
|
|
2270
|
+
if (opts.trustTier !== void 0) {
|
|
2271
|
+
record._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
2272
|
+
}
|
|
2221
2273
|
})
|
|
2222
2274
|
);
|
|
2223
2275
|
await ctx.database.batch(...prepared);
|
|
@@ -2278,6 +2330,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
2278
2330
|
supersededBy: raw.superseded_by ?? null,
|
|
2279
2331
|
supersededAt: raw.superseded_at ?? null,
|
|
2280
2332
|
lastObservedAt: raw.last_observed_at ?? null,
|
|
2333
|
+
factType: raw.fact_type ?? null,
|
|
2334
|
+
archivedAt: raw.archived_at ?? null,
|
|
2335
|
+
trustTier: raw.trust_tier ?? null,
|
|
2281
2336
|
createdAt: new Date(raw.created_at),
|
|
2282
2337
|
updatedAt: new Date(raw.updated_at),
|
|
2283
2338
|
isDeleted: raw.is_deleted === true || raw.is_deleted === 1
|
|
@@ -2295,6 +2350,7 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
2295
2350
|
...baseVaultConditions(ctx, options),
|
|
2296
2351
|
...options?.scopes?.length ? [Q3.where("scope", Q3.oneOf(options.scopes))] : [],
|
|
2297
2352
|
...options?.folderId !== void 0 ? [Q3.where("folder_id", options.folderId)] : [],
|
|
2353
|
+
...options?.factTypes?.length ? [Q3.where("fact_type", Q3.oneOf(options.factTypes))] : [],
|
|
2298
2354
|
Q3.sortBy(options?.since ? "updated_at" : "created_at", Q3.desc),
|
|
2299
2355
|
...options?.limit !== null && options?.limit !== void 0 && options.limit > 0 ? [Q3.take(options.limit)] : []
|
|
2300
2356
|
];
|
|
@@ -2316,6 +2372,14 @@ async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
|
2316
2372
|
return stored.content;
|
|
2317
2373
|
});
|
|
2318
2374
|
}
|
|
2375
|
+
async function countActiveVaultMemoriesOp(ctx) {
|
|
2376
|
+
return ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx)).fetchCount();
|
|
2377
|
+
}
|
|
2378
|
+
async function getActiveVaultMemoryIdsOp(ctx, ids) {
|
|
2379
|
+
if (ids.length === 0) return /* @__PURE__ */ new Set();
|
|
2380
|
+
const rows = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx), Q3.where("id", Q3.oneOf(ids))).unsafeFetchRaw();
|
|
2381
|
+
return new Set(rows.map((r) => r.id));
|
|
2382
|
+
}
|
|
2319
2383
|
async function updateVaultMemoryOp(ctx, id, opts) {
|
|
2320
2384
|
try {
|
|
2321
2385
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -2369,6 +2433,15 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
2369
2433
|
if (opts.lastObservedAt !== void 0) {
|
|
2370
2434
|
r._setRaw("last_observed_at", opts.lastObservedAt);
|
|
2371
2435
|
}
|
|
2436
|
+
if (opts.factType !== void 0) {
|
|
2437
|
+
r._setRaw("fact_type", opts.factType);
|
|
2438
|
+
}
|
|
2439
|
+
if (opts.trustTier !== void 0) {
|
|
2440
|
+
r._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
2441
|
+
}
|
|
2442
|
+
if (opts.restore) {
|
|
2443
|
+
r._setRaw("archived_at", null);
|
|
2444
|
+
}
|
|
2372
2445
|
if (opts.preserveUpdatedAt) {
|
|
2373
2446
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
2374
2447
|
}
|
|
@@ -2568,6 +2641,98 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
2568
2641
|
}
|
|
2569
2642
|
return records.length;
|
|
2570
2643
|
}
|
|
2644
|
+
function assertVaultScopeForSweep(ctx) {
|
|
2645
|
+
if (ctx.userId === void 0 && ctx.singleTenant !== true) {
|
|
2646
|
+
throw new Error(
|
|
2647
|
+
"Refusing to run a decay sweep on an unscoped vault context: it has no userId and is not marked singleTenant, so it would sweep across all tenants. Set ctx.userId on server/multi-tenant contexts, or ctx.singleTenant = true on a per-wallet, physically single-tenant client DB. (walletAddress alone is no longer accepted \u2014 it does not scope the sweep query.)"
|
|
2648
|
+
);
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
async function getDecayCandidatesRawOp(ctx) {
|
|
2652
|
+
assertVaultScopeForSweep(ctx);
|
|
2653
|
+
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true })).unsafeFetchRaw();
|
|
2654
|
+
return results.map((raw) => ({
|
|
2655
|
+
uniqueId: raw.id,
|
|
2656
|
+
factType: raw.fact_type ?? null,
|
|
2657
|
+
eventTimeEnd: raw.event_time_end ?? null,
|
|
2658
|
+
eventTimeKind: raw.event_time_kind ?? null,
|
|
2659
|
+
updatedAt: raw.updated_at,
|
|
2660
|
+
archivedAt: raw.archived_at ?? null,
|
|
2661
|
+
source: raw.source ?? null,
|
|
2662
|
+
trustTier: raw.trust_tier ?? null
|
|
2663
|
+
}));
|
|
2664
|
+
}
|
|
2665
|
+
async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
2666
|
+
try {
|
|
2667
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
2668
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2669
|
+
let stale = false;
|
|
2670
|
+
const archivedAtValue = opts?.now ?? Date.now();
|
|
2671
|
+
await ctx.database.write(async () => {
|
|
2672
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
|
|
2673
|
+
stale = true;
|
|
2674
|
+
return;
|
|
2675
|
+
}
|
|
2676
|
+
if (opts?.expectedUpdatedAt !== void 0 && record.updatedAt.getTime() !== opts.expectedUpdatedAt) {
|
|
2677
|
+
stale = true;
|
|
2678
|
+
return;
|
|
2679
|
+
}
|
|
2680
|
+
await record.update((r) => {
|
|
2681
|
+
r._setRaw("archived_at", archivedAtValue);
|
|
2682
|
+
});
|
|
2683
|
+
});
|
|
2684
|
+
return !stale;
|
|
2685
|
+
} catch {
|
|
2686
|
+
return false;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
async function restoreVaultMemoryOp(ctx, id) {
|
|
2690
|
+
try {
|
|
2691
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
2692
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2693
|
+
let stale = false;
|
|
2694
|
+
await ctx.database.write(async () => {
|
|
2695
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
2696
|
+
stale = true;
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
await record.update((r) => {
|
|
2700
|
+
r._setRaw("archived_at", null);
|
|
2701
|
+
});
|
|
2702
|
+
});
|
|
2703
|
+
return !stale;
|
|
2704
|
+
} catch {
|
|
2705
|
+
return false;
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
2709
|
+
try {
|
|
2710
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
2711
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2712
|
+
const now = opts.now ?? Date.now();
|
|
2713
|
+
let stale = false;
|
|
2714
|
+
await ctx.database.write(async () => {
|
|
2715
|
+
const archivedAt = record.archivedAt;
|
|
2716
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
2717
|
+
stale = true;
|
|
2718
|
+
return;
|
|
2719
|
+
}
|
|
2720
|
+
await record.update((r) => {
|
|
2721
|
+
r._setRaw("is_deleted", true);
|
|
2722
|
+
});
|
|
2723
|
+
});
|
|
2724
|
+
if (stale) return false;
|
|
2725
|
+
if (ctx.entityCtx) {
|
|
2726
|
+
try {
|
|
2727
|
+
await unlinkMemoryEntitiesOp(ctx.entityCtx, [id]);
|
|
2728
|
+
} catch {
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
return true;
|
|
2732
|
+
} catch {
|
|
2733
|
+
return false;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2571
2736
|
async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel) {
|
|
2572
2737
|
try {
|
|
2573
2738
|
const record = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -2747,6 +2912,9 @@ async function withEmbeddingRetry(call) {
|
|
|
2747
2912
|
}
|
|
2748
2913
|
}
|
|
2749
2914
|
if (threw) throw lastThrown;
|
|
2915
|
+
if (last?.error instanceof Error && last.response?.status === void 0) {
|
|
2916
|
+
throw last.error;
|
|
2917
|
+
}
|
|
2750
2918
|
return last;
|
|
2751
2919
|
}
|
|
2752
2920
|
var EmbeddingHttpError = class extends Error {
|
|
@@ -3593,6 +3761,7 @@ function rankVaultMemories(_query, queryEmbedding, items, options) {
|
|
|
3593
3761
|
sourceChunkIds: item.sourceChunkIds,
|
|
3594
3762
|
eventTimeEnd: item.eventTimeEnd,
|
|
3595
3763
|
eventTimeKind: item.eventTimeKind,
|
|
3764
|
+
factType: item.factType,
|
|
3596
3765
|
similarity: cosineSimilarity(queryEmbedding, item.embedding)
|
|
3597
3766
|
}));
|
|
3598
3767
|
const filtered = scored.filter((r) => r.similarity >= minSimilarity);
|
|
@@ -3643,6 +3812,7 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
|
|
|
3643
3812
|
const recencyAlpha = options?.recencyAlpha ?? 1;
|
|
3644
3813
|
const proofCountAlpha = options?.proofCountAlpha ?? 0.1;
|
|
3645
3814
|
const bm25AdmissionDivisor = options?.bm25AdmissionDivisor ?? 50;
|
|
3815
|
+
const factTypeWeights = options?.factTypeWeights;
|
|
3646
3816
|
if (items.length === 0) return [];
|
|
3647
3817
|
const baseRanked = rankVaultMemories(query, queryEmbedding, items, {
|
|
3648
3818
|
limit: items.length,
|
|
@@ -3674,7 +3844,8 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
|
|
|
3674
3844
|
eventTimeStart: item.eventTimeStart,
|
|
3675
3845
|
sourceChunkIds: item.sourceChunkIds,
|
|
3676
3846
|
eventTimeEnd: item.eventTimeEnd,
|
|
3677
|
-
eventTimeKind: item.eventTimeKind
|
|
3847
|
+
eventTimeKind: item.eventTimeKind,
|
|
3848
|
+
factType: item.factType
|
|
3678
3849
|
});
|
|
3679
3850
|
}
|
|
3680
3851
|
const boostFor = (id) => {
|
|
@@ -3683,7 +3854,9 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
|
|
|
3683
3854
|
const recencyBoost = 1 + recencyAlpha * (recency - 0.5);
|
|
3684
3855
|
const proofCount = Math.max(1, item?.proofCount ?? 1);
|
|
3685
3856
|
const proofBoost = 1 + proofCountAlpha * Math.log(1 + proofCount) - proofCountAlpha * Math.log(2);
|
|
3686
|
-
|
|
3857
|
+
const rawTypeWeight = item?.factType ? factTypeWeights?.[item.factType] : void 0;
|
|
3858
|
+
const typeWeight = rawTypeWeight !== void 0 && Number.isFinite(rawTypeWeight) && rawTypeWeight > 0 ? rawTypeWeight : 1;
|
|
3859
|
+
return recencyBoost * proofBoost * typeWeight;
|
|
3687
3860
|
};
|
|
3688
3861
|
let combined = [...baseRanked, ...admitted].map((r) => ({
|
|
3689
3862
|
...r,
|
|
@@ -3735,7 +3908,8 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3735
3908
|
supersessionWindow: options?.supersessionWindow,
|
|
3736
3909
|
proofCountAlpha: options?.proofCountAlpha,
|
|
3737
3910
|
bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
|
|
3738
|
-
rrfK: options?.rrfK
|
|
3911
|
+
rrfK: options?.rrfK,
|
|
3912
|
+
...options?.factTypeWeights && { factTypeWeights: options.factTypeWeights }
|
|
3739
3913
|
});
|
|
3740
3914
|
if (options?.v2HeadStats) {
|
|
3741
3915
|
options.v2HeadStats.hadResults = v2Ranked.length > 0;
|
|
@@ -3828,7 +4002,8 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3828
4002
|
eventTimeStart: orig?.eventTimeStart,
|
|
3829
4003
|
sourceChunkIds: orig?.sourceChunkIds,
|
|
3830
4004
|
eventTimeEnd: orig?.eventTimeEnd,
|
|
3831
|
-
eventTimeKind: orig?.eventTimeKind
|
|
4005
|
+
eventTimeKind: orig?.eventTimeKind,
|
|
4006
|
+
factType: orig?.factType
|
|
3832
4007
|
};
|
|
3833
4008
|
});
|
|
3834
4009
|
const remainingTail = combined.filter((r) => !pickedIds.has(r.uniqueId));
|
|
@@ -3854,7 +4029,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
3854
4029
|
...options?.bm25AdmissionDivisor !== void 0 && {
|
|
3855
4030
|
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
3856
4031
|
},
|
|
3857
|
-
...options?.rrfK !== void 0 && { rrfK: options.rrfK }
|
|
4032
|
+
...options?.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
4033
|
+
...options?.factTypeWeights && { factTypeWeights: options.factTypeWeights }
|
|
3858
4034
|
};
|
|
3859
4035
|
const originalRanked = rankFusedVaultMemories(originalQuery, originalQueryEmbedding, items, {
|
|
3860
4036
|
limit: perFacetTopN,
|
|
@@ -3892,7 +4068,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
3892
4068
|
eventTimeStart: item.eventTimeStart,
|
|
3893
4069
|
sourceChunkIds: item.sourceChunkIds,
|
|
3894
4070
|
eventTimeEnd: item.eventTimeEnd,
|
|
3895
|
-
eventTimeKind: item.eventTimeKind
|
|
4071
|
+
eventTimeKind: item.eventTimeKind,
|
|
4072
|
+
factType: item.factType
|
|
3896
4073
|
};
|
|
3897
4074
|
}
|
|
3898
4075
|
);
|
|
@@ -3916,7 +4093,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
3916
4093
|
eventTimeStart: item.eventTimeStart,
|
|
3917
4094
|
sourceChunkIds: item.sourceChunkIds,
|
|
3918
4095
|
eventTimeEnd: item.eventTimeEnd,
|
|
3919
|
-
eventTimeKind: item.eventTimeKind
|
|
4096
|
+
eventTimeKind: item.eventTimeKind,
|
|
4097
|
+
factType: item.factType
|
|
3920
4098
|
});
|
|
3921
4099
|
}
|
|
3922
4100
|
}
|
|
@@ -3973,7 +4151,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
3973
4151
|
eventTimeStart: orig?.eventTimeStart,
|
|
3974
4152
|
sourceChunkIds: orig?.sourceChunkIds,
|
|
3975
4153
|
eventTimeEnd: orig?.eventTimeEnd,
|
|
3976
|
-
eventTimeKind: orig?.eventTimeKind
|
|
4154
|
+
eventTimeKind: orig?.eventTimeKind,
|
|
4155
|
+
factType: orig?.factType
|
|
3977
4156
|
};
|
|
3978
4157
|
});
|
|
3979
4158
|
const remainingTail = combined.filter((r) => !pickedIds.has(r.uniqueId));
|
|
@@ -4045,6 +4224,8 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4045
4224
|
const queryOpts = {};
|
|
4046
4225
|
if (scopes?.length) queryOpts.scopes = scopes;
|
|
4047
4226
|
if (folderId !== void 0) queryOpts.folderId = folderId;
|
|
4227
|
+
if (searchOptions?.factTypes?.length) queryOpts.factTypes = searchOptions.factTypes;
|
|
4228
|
+
if (searchOptions?.includeArchived) queryOpts.includeArchived = true;
|
|
4048
4229
|
const loaded = await getAllVaultMemoriesOp(
|
|
4049
4230
|
vaultCtx,
|
|
4050
4231
|
Object.keys(queryOpts).length > 0 ? queryOpts : void 0
|
|
@@ -4116,7 +4297,8 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4116
4297
|
eventTimeStart: m.eventTimeStart,
|
|
4117
4298
|
sourceChunkIds: m.sourceChunkIds,
|
|
4118
4299
|
eventTimeEnd: m.eventTimeEnd,
|
|
4119
|
-
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind)
|
|
4300
|
+
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
4301
|
+
factType: m.factType
|
|
4120
4302
|
}));
|
|
4121
4303
|
if (queryEmbedding.length > 0) {
|
|
4122
4304
|
const mismatched = embeddedItems.filter(
|
|
@@ -4160,7 +4342,8 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4160
4342
|
...searchOptions?.bm25AdmissionDivisor !== void 0 && {
|
|
4161
4343
|
bm25AdmissionDivisor: searchOptions.bm25AdmissionDivisor
|
|
4162
4344
|
},
|
|
4163
|
-
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK }
|
|
4345
|
+
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
4346
|
+
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
4164
4347
|
};
|
|
4165
4348
|
if (useFusion && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
4166
4349
|
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
@@ -4327,7 +4510,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
4327
4510
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
4328
4511
|
);
|
|
4329
4512
|
}
|
|
4330
|
-
const { recall: recall2 } = await import("./recall-
|
|
4513
|
+
const { recall: recall2 } = await import("./recall-C3LJ5R2E.mjs");
|
|
4331
4514
|
const result = await recall2(
|
|
4332
4515
|
query,
|
|
4333
4516
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
@@ -4438,6 +4621,159 @@ function extractQueryEntities(query) {
|
|
|
4438
4621
|
return [...seen];
|
|
4439
4622
|
}
|
|
4440
4623
|
|
|
4624
|
+
// src/lib/memory/graphTraversal.ts
|
|
4625
|
+
var MAX_HOPS = 2;
|
|
4626
|
+
var ENTITY_FANOUT = 8;
|
|
4627
|
+
var MIN_REFINER_CANDIDATES = 16;
|
|
4628
|
+
var MAX_REFINER_CANDIDATES = 64;
|
|
4629
|
+
var NODE_BUDGET = 64;
|
|
4630
|
+
var VAULT_SIZE_HOP_CAP = 1e3;
|
|
4631
|
+
function clampPositiveInt(value, fallback) {
|
|
4632
|
+
if (value === void 0 || !Number.isFinite(value) || value < 1) return fallback;
|
|
4633
|
+
return Math.floor(value);
|
|
4634
|
+
}
|
|
4635
|
+
function capHopsForDensity(maxHops, vaultSize) {
|
|
4636
|
+
if (vaultSize !== void 0 && vaultSize > VAULT_SIZE_HOP_CAP) return Math.min(maxHops, 1);
|
|
4637
|
+
return maxHops;
|
|
4638
|
+
}
|
|
4639
|
+
function rankMemoriesByOverlap(map) {
|
|
4640
|
+
return [...map.entries()].sort((a, b) => b[1].size - a[1].size).map(([memoryId]) => memoryId);
|
|
4641
|
+
}
|
|
4642
|
+
async function traverseGraphLane(query, entityCtx, options = {}) {
|
|
4643
|
+
const seedNames = extractQueryEntities(query);
|
|
4644
|
+
if (seedNames.length === 0) return [];
|
|
4645
|
+
const entityFanout = clampPositiveInt(options.entityFanout, ENTITY_FANOUT);
|
|
4646
|
+
const nodeBudget = clampPositiveInt(options.nodeBudget, NODE_BUDGET);
|
|
4647
|
+
const maxHops = capHopsForDensity(clampPositiveInt(options.maxHops, MAX_HOPS), options.vaultSize);
|
|
4648
|
+
const keepActive = async (map) => {
|
|
4649
|
+
if (!options.filterActiveMemoryIds || map.size === 0) return map;
|
|
4650
|
+
const active = await options.filterActiveMemoryIds([...map.keys()]);
|
|
4651
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
4652
|
+
for (const [id, names] of map) if (active.has(id)) filtered.set(id, names);
|
|
4653
|
+
return filtered;
|
|
4654
|
+
};
|
|
4655
|
+
const hop1 = await keepActive(await getMemoriesByEntityNamesOp(entityCtx, seedNames));
|
|
4656
|
+
if (hop1.size === 0) return [];
|
|
4657
|
+
const hop1Ranking = rankMemoriesByOverlap(hop1);
|
|
4658
|
+
if (maxHops <= 1) return hop1Ranking;
|
|
4659
|
+
const hop1Emitted = hop1Ranking.slice(0, nodeBudget);
|
|
4660
|
+
const perHopRankings = [hop1Emitted];
|
|
4661
|
+
const firstHopOf = /* @__PURE__ */ new Map();
|
|
4662
|
+
for (const id of hop1Emitted) if (!firstHopOf.has(id)) firstHopOf.set(id, 1);
|
|
4663
|
+
const accumulated = new Set(hop1Emitted);
|
|
4664
|
+
const seenEntities = new Set(seedNames);
|
|
4665
|
+
let frontier = hop1Emitted;
|
|
4666
|
+
for (let hop = 2; hop <= maxHops; hop++) {
|
|
4667
|
+
if (frontier.length === 0) break;
|
|
4668
|
+
if (accumulated.size >= nodeBudget) break;
|
|
4669
|
+
const memoryToEntities = await getEntitiesByMemoryIdsOp(entityCtx, frontier);
|
|
4670
|
+
const neighborCounts = /* @__PURE__ */ new Map();
|
|
4671
|
+
for (const names of memoryToEntities.values()) {
|
|
4672
|
+
for (const name of names) {
|
|
4673
|
+
if (seenEntities.has(name)) continue;
|
|
4674
|
+
neighborCounts.set(name, (neighborCounts.get(name) ?? 0) + 1);
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
if (neighborCounts.size === 0) break;
|
|
4678
|
+
const rankedNeighbors = [...neighborCounts.entries()].sort((a, b) => b[1] - a[1]).map(([name]) => name);
|
|
4679
|
+
let topNeighbors = rankedNeighbors.slice(0, entityFanout);
|
|
4680
|
+
if (options.refineNeighbors && rankedNeighbors.length > entityFanout) {
|
|
4681
|
+
try {
|
|
4682
|
+
const refinerCandidateCap = Math.min(
|
|
4683
|
+
Math.max(entityFanout * 2, MIN_REFINER_CANDIDATES),
|
|
4684
|
+
MAX_REFINER_CANDIDATES
|
|
4685
|
+
);
|
|
4686
|
+
const refinerCandidates = rankedNeighbors.slice(0, refinerCandidateCap);
|
|
4687
|
+
const refined = await options.refineNeighbors.refine(
|
|
4688
|
+
query,
|
|
4689
|
+
refinerCandidates,
|
|
4690
|
+
entityFanout
|
|
4691
|
+
);
|
|
4692
|
+
const valid = [];
|
|
4693
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4694
|
+
for (const name of refined) {
|
|
4695
|
+
if (!neighborCounts.has(name) || seen.has(name)) continue;
|
|
4696
|
+
seen.add(name);
|
|
4697
|
+
valid.push(name);
|
|
4698
|
+
if (valid.length >= entityFanout) break;
|
|
4699
|
+
}
|
|
4700
|
+
if (valid.length > 0) topNeighbors = valid;
|
|
4701
|
+
} catch (err) {
|
|
4702
|
+
getLogger().warn(
|
|
4703
|
+
`[memory/graph] neighbor refine failed; using co-occurrence order: ${err instanceof Error ? err.message : String(err)}`
|
|
4704
|
+
);
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
for (const name of topNeighbors) seenEntities.add(name);
|
|
4708
|
+
const hopMap = await keepActive(await getMemoriesByEntityNamesOp(entityCtx, topNeighbors));
|
|
4709
|
+
if (hopMap.size === 0) break;
|
|
4710
|
+
const hopRanking = rankMemoriesByOverlap(hopMap);
|
|
4711
|
+
const newlyDiscovered = [];
|
|
4712
|
+
for (const id of hopRanking) {
|
|
4713
|
+
if (accumulated.has(id)) continue;
|
|
4714
|
+
accumulated.add(id);
|
|
4715
|
+
newlyDiscovered.push(id);
|
|
4716
|
+
firstHopOf.set(id, hop);
|
|
4717
|
+
if (accumulated.size >= nodeBudget) break;
|
|
4718
|
+
}
|
|
4719
|
+
if (newlyDiscovered.length === 0) break;
|
|
4720
|
+
perHopRankings.push(newlyDiscovered);
|
|
4721
|
+
frontier = newlyDiscovered;
|
|
4722
|
+
}
|
|
4723
|
+
const fused = rrfFuse(perHopRankings, options.rrfK);
|
|
4724
|
+
return [...fused.entries()].sort((a, b) => {
|
|
4725
|
+
const hopA = firstHopOf.get(a[0]) ?? Infinity;
|
|
4726
|
+
const hopB = firstHopOf.get(b[0]) ?? Infinity;
|
|
4727
|
+
if (hopA !== hopB) return hopA - hopB;
|
|
4728
|
+
return b[1] - a[1];
|
|
4729
|
+
}).map(([id]) => id);
|
|
4730
|
+
}
|
|
4731
|
+
var DEFAULT_REFINER_MODEL = "inclusionai/ling-2.6-flash";
|
|
4732
|
+
var DEFAULT_REFINER_ATTEMPTS = 1;
|
|
4733
|
+
var DEFAULT_REFINER_TOTAL_TIMEOUT_MS = 8e3;
|
|
4734
|
+
function createLlmNeighborRefiner(options) {
|
|
4735
|
+
return {
|
|
4736
|
+
async refine(query, candidates, limit) {
|
|
4737
|
+
if (candidates.length === 0) return [];
|
|
4738
|
+
const numbered = candidates.map((name, i) => `[${i + 1}] ${name}`).join("\n");
|
|
4739
|
+
const systemPrompt = `You help a memory-retrieval system decide which related topics to explore.
|
|
4740
|
+
|
|
4741
|
+
Given a user's question and a numbered list of candidate topics/entities linked to memories found so far, pick the ones most likely to lead to memories that help ANSWER the question. Choose at most ${limit}. Prefer topics semantically related to the question; ignore incidental ones.
|
|
4742
|
+
|
|
4743
|
+
Output strict JSON, no prose: { "expand": [<entity names to expand, verbatim from the list>] }`;
|
|
4744
|
+
const parsed = await callPortalJsonCompletion({
|
|
4745
|
+
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
4746
|
+
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
4747
|
+
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
4748
|
+
model: options.model ?? DEFAULT_REFINER_MODEL,
|
|
4749
|
+
systemPrompt,
|
|
4750
|
+
userMessage: `Question: ${query}
|
|
4751
|
+
|
|
4752
|
+
Candidate topics:
|
|
4753
|
+
${numbered}
|
|
4754
|
+
|
|
4755
|
+
Which should be expanded?`,
|
|
4756
|
+
tag: "memory/graph-refine",
|
|
4757
|
+
maxAttempts: options.maxAttempts ?? DEFAULT_REFINER_ATTEMPTS,
|
|
4758
|
+
totalTimeoutMs: options.totalTimeoutMs ?? DEFAULT_REFINER_TOTAL_TIMEOUT_MS,
|
|
4759
|
+
...options.backoffMs && { backoffMs: options.backoffMs },
|
|
4760
|
+
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
4761
|
+
});
|
|
4762
|
+
if (parsed === null || typeof parsed !== "object") return [];
|
|
4763
|
+
const list = parsed.expand;
|
|
4764
|
+
if (!Array.isArray(list)) return [];
|
|
4765
|
+
const byNormalized = new Map(candidates.map((c) => [normalizeEntityName(c), c]));
|
|
4766
|
+
const out = [];
|
|
4767
|
+
for (const raw of list) {
|
|
4768
|
+
if (typeof raw !== "string") continue;
|
|
4769
|
+
const match = byNormalized.get(normalizeEntityName(raw));
|
|
4770
|
+
if (match) out.push(match);
|
|
4771
|
+
}
|
|
4772
|
+
return out;
|
|
4773
|
+
}
|
|
4774
|
+
};
|
|
4775
|
+
}
|
|
4776
|
+
|
|
4441
4777
|
// src/lib/memory/queryTemporal.ts
|
|
4442
4778
|
var RELATIVE_DAY_ENTRIES = [
|
|
4443
4779
|
[/\btoday\b/, "today", 0],
|
|
@@ -4650,12 +4986,12 @@ var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
|
4650
4986
|
function flagsForBudget(budget) {
|
|
4651
4987
|
switch (budget) {
|
|
4652
4988
|
case "high":
|
|
4653
|
-
return { rerank: true, decompose: true };
|
|
4989
|
+
return { rerank: true, decompose: true, traverse: true };
|
|
4654
4990
|
case "mid":
|
|
4655
|
-
return { rerank: true, decompose: false };
|
|
4991
|
+
return { rerank: true, decompose: false, traverse: false };
|
|
4656
4992
|
case "low":
|
|
4657
4993
|
default:
|
|
4658
|
-
return { rerank: false, decompose: false };
|
|
4994
|
+
return { rerank: false, decompose: false, traverse: false };
|
|
4659
4995
|
}
|
|
4660
4996
|
}
|
|
4661
4997
|
function dedupeBy(items, ...keys) {
|
|
@@ -4723,11 +5059,25 @@ async function recall(query, ctx, options = {}) {
|
|
|
4723
5059
|
}
|
|
4724
5060
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
4725
5061
|
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
5062
|
+
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
4726
5063
|
const prepStart = nowMs();
|
|
4727
5064
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
4728
5065
|
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
|
|
4729
|
-
|
|
4730
|
-
|
|
5066
|
+
// The graph + temporal lanes are AUXILIARY (RRF side-signals). A transient
|
|
5067
|
+
// WatermelonDB throw in either must NOT reject this Promise.all and take
|
|
5068
|
+
// PRIMARY cosine/BM25 recall down with it — degrade the failing lane to an
|
|
5069
|
+
// empty ranking instead (mirrors safeCountVault's fail-soft posture).
|
|
5070
|
+
safeLane(
|
|
5071
|
+
"graph",
|
|
5072
|
+
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
5073
|
+
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
5074
|
+
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
5075
|
+
...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
|
|
5076
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
5077
|
+
...graphRefiner && { refineNeighbors: graphRefiner }
|
|
5078
|
+
})
|
|
5079
|
+
),
|
|
5080
|
+
wantsTemporal ? safeLane("temporal", () => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)) : Promise.resolve([])
|
|
4731
5081
|
]);
|
|
4732
5082
|
prepMs = nowMs() - prepStart;
|
|
4733
5083
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
@@ -4777,6 +5127,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
4777
5127
|
},
|
|
4778
5128
|
...options.scopes && { scopes: options.scopes },
|
|
4779
5129
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
5130
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
5131
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
4780
5132
|
...entityRanking.length > 0 && { entityRanking },
|
|
4781
5133
|
...temporalRanking.length > 0 && { temporalRanking }
|
|
4782
5134
|
}
|
|
@@ -4898,6 +5250,9 @@ function toFactMemory(r) {
|
|
|
4898
5250
|
...r.eventTimeStart !== void 0 && { eventTimeStart: r.eventTimeStart },
|
|
4899
5251
|
...r.eventTimeEnd !== void 0 && { eventTimeEnd: r.eventTimeEnd },
|
|
4900
5252
|
...r.eventTimeKind !== void 0 && { eventTimeKind: r.eventTimeKind },
|
|
5253
|
+
// Typed memory (PR1) — surfaced from VaultSearchResult so recall results
|
|
5254
|
+
// (and UI reading them) carry the fact's type. Undefined when untyped.
|
|
5255
|
+
...r.factType !== void 0 && { factType: r.factType },
|
|
4901
5256
|
...r.sourceChunkIds !== void 0 && r.sourceChunkIds !== null && { sourceChunkIds: r.sourceChunkIds },
|
|
4902
5257
|
// r.similarity from searchVaultMemoriesWithSize is the fused score
|
|
4903
5258
|
// (cosine + BM25 + RRF + recency + proof) when useFusion=true (the
|
|
@@ -4911,14 +5266,47 @@ function toFactMemory(r) {
|
|
|
4911
5266
|
updatedAt: r.updatedAt ?? /* @__PURE__ */ new Date(0)
|
|
4912
5267
|
};
|
|
4913
5268
|
}
|
|
4914
|
-
async function buildGraphLaneRanking(query, ctx) {
|
|
5269
|
+
async function buildGraphLaneRanking(query, ctx, traverse = false, traversalOptions = {}) {
|
|
4915
5270
|
const entityCtx = ctx.entityCtx ?? ctx.vaultCtx?.entityCtx;
|
|
4916
5271
|
if (!entityCtx) return [];
|
|
5272
|
+
if (traverse) {
|
|
5273
|
+
const vaultSize = await safeCountVault(ctx);
|
|
5274
|
+
const vaultCtx2 = ctx.vaultCtx;
|
|
5275
|
+
return traverseGraphLane(query, entityCtx, {
|
|
5276
|
+
...traversalOptions,
|
|
5277
|
+
...vaultSize !== void 0 && { vaultSize },
|
|
5278
|
+
...vaultCtx2 && {
|
|
5279
|
+
filterActiveMemoryIds: (ids) => getActiveVaultMemoryIdsOp(vaultCtx2, ids)
|
|
5280
|
+
}
|
|
5281
|
+
});
|
|
5282
|
+
}
|
|
4917
5283
|
const queryEntities = extractQueryEntities(query);
|
|
4918
5284
|
if (queryEntities.length === 0) return [];
|
|
4919
5285
|
const memoryToEntities = await getMemoriesByEntityNamesOp(entityCtx, queryEntities);
|
|
4920
5286
|
if (memoryToEntities.size === 0) return [];
|
|
4921
|
-
|
|
5287
|
+
const ranked = [...memoryToEntities.entries()].sort((a, b) => b[1].size - a[1].size).map(([memoryId]) => memoryId);
|
|
5288
|
+
const vaultCtx = ctx.vaultCtx;
|
|
5289
|
+
if (!vaultCtx) return ranked;
|
|
5290
|
+
const activeIds = await getActiveVaultMemoryIdsOp(vaultCtx, ranked);
|
|
5291
|
+
return ranked.filter((id) => activeIds.has(id));
|
|
5292
|
+
}
|
|
5293
|
+
async function safeCountVault(ctx) {
|
|
5294
|
+
if (!ctx.vaultCtx) return void 0;
|
|
5295
|
+
try {
|
|
5296
|
+
return await countActiveVaultMemoriesOp(ctx.vaultCtx);
|
|
5297
|
+
} catch {
|
|
5298
|
+
return void 0;
|
|
5299
|
+
}
|
|
5300
|
+
}
|
|
5301
|
+
async function safeLane(label, run) {
|
|
5302
|
+
try {
|
|
5303
|
+
return await run();
|
|
5304
|
+
} catch (err) {
|
|
5305
|
+
getLogger().warn(
|
|
5306
|
+
`[memory/recall] ${label} lane failed; continuing without it: ${err instanceof Error ? err.message : String(err)}`
|
|
5307
|
+
);
|
|
5308
|
+
return [];
|
|
5309
|
+
}
|
|
4922
5310
|
}
|
|
4923
5311
|
async function buildTemporalLaneRanking(query, vaultCtx, now) {
|
|
4924
5312
|
const window2 = parseQueryTimeWindow(query, now);
|
|
@@ -5024,12 +5412,24 @@ export {
|
|
|
5024
5412
|
getMemoriesNeedingTopicExtractionOp,
|
|
5025
5413
|
stampTopicsExtractedAtOp,
|
|
5026
5414
|
deleteAllVaultMemoriesForUserOp,
|
|
5415
|
+
assertVaultScopeForSweep,
|
|
5416
|
+
getDecayCandidatesRawOp,
|
|
5417
|
+
archiveVaultMemoryOp,
|
|
5418
|
+
restoreVaultMemoryOp,
|
|
5419
|
+
hardDeleteDecayedOp,
|
|
5027
5420
|
updateVaultMemoryEmbeddingOp,
|
|
5028
5421
|
RerankerUnavailableError,
|
|
5029
5422
|
isRerankerAvailable,
|
|
5030
5423
|
DEFAULT_VAULT_CACHE_SIZE,
|
|
5031
5424
|
LRUCache,
|
|
5032
5425
|
createVaultEmbeddingCache,
|
|
5426
|
+
MAX_HOPS,
|
|
5427
|
+
ENTITY_FANOUT,
|
|
5428
|
+
NODE_BUDGET,
|
|
5429
|
+
VAULT_SIZE_HOP_CAP,
|
|
5430
|
+
capHopsForDensity,
|
|
5431
|
+
traverseGraphLane,
|
|
5432
|
+
createLlmNeighborRefiner,
|
|
5033
5433
|
recall,
|
|
5034
5434
|
preEmbedVaultMemories,
|
|
5035
5435
|
eagerEmbedContent,
|