@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
|
@@ -2105,6 +2105,36 @@ async function getMemoriesByEntityNamesOp(ctx, entityNames) {
|
|
|
2105
2105
|
}
|
|
2106
2106
|
return out;
|
|
2107
2107
|
}
|
|
2108
|
+
async function getEntitiesByMemoryIdsOp(ctx, memoryIds) {
|
|
2109
|
+
const unique = Array.from(new Set(memoryIds.filter((id) => id.length > 0)));
|
|
2110
|
+
if (unique.length === 0) return /* @__PURE__ */ new Map();
|
|
2111
|
+
const linkConditions = [Q2.where("memory_id", Q2.oneOf(unique))];
|
|
2112
|
+
if (ctx.userId !== void 0) {
|
|
2113
|
+
if (ctx.allowUnscopedRows) {
|
|
2114
|
+
linkConditions.push(Q2.or(Q2.where("user_id", ctx.userId), Q2.where("user_id", null)));
|
|
2115
|
+
} else {
|
|
2116
|
+
linkConditions.push(Q2.where("user_id", ctx.userId));
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
const links = await ctx.memoryEntityCollection.query(...linkConditions).fetch();
|
|
2120
|
+
if (links.length === 0) return /* @__PURE__ */ new Map();
|
|
2121
|
+
const entityIds = Array.from(new Set(links.map((l) => String(l.entityId))));
|
|
2122
|
+
const entityRows = await ctx.entityCollection.query(Q2.where("id", Q2.oneOf(entityIds))).fetch();
|
|
2123
|
+
const entityIdToName = new Map(entityRows.map((e) => [e.id, e.canonicalName]));
|
|
2124
|
+
const out = /* @__PURE__ */ new Map();
|
|
2125
|
+
for (const link of links) {
|
|
2126
|
+
const entityName = entityIdToName.get(String(link.entityId));
|
|
2127
|
+
if (!entityName) continue;
|
|
2128
|
+
const memoryId = String(link.memoryId);
|
|
2129
|
+
let bucket = out.get(memoryId);
|
|
2130
|
+
if (!bucket) {
|
|
2131
|
+
bucket = /* @__PURE__ */ new Set();
|
|
2132
|
+
out.set(memoryId, bucket);
|
|
2133
|
+
}
|
|
2134
|
+
bucket.add(entityName);
|
|
2135
|
+
}
|
|
2136
|
+
return out;
|
|
2137
|
+
}
|
|
2108
2138
|
|
|
2109
2139
|
// src/lib/db/memoryVault/operations.ts
|
|
2110
2140
|
import { Q as Q3 } from "@nozbe/watermelondb";
|
|
@@ -2142,11 +2172,18 @@ function isOwnedByCtxUser(ctx, record) {
|
|
|
2142
2172
|
function baseVaultConditions(ctx, options) {
|
|
2143
2173
|
return [
|
|
2144
2174
|
...options?.includeDeleted ? [] : [Q3.where("is_deleted", false)],
|
|
2175
|
+
...options?.includeArchived ? [] : [Q3.where("archived_at", Q3.eq(null))],
|
|
2176
|
+
...options?.includeQuarantined ? [] : [Q3.where("trust_tier", Q3.notEq("quarantined"))],
|
|
2145
2177
|
...options?.includeSuperseded ? [] : [Q3.where("superseded_by", null)],
|
|
2146
2178
|
...ctx.userId !== void 0 ? [Q3.where("user_id", ctx.userId)] : [],
|
|
2147
2179
|
...options?.since ? [Q3.where("updated_at", Q3.gt(options.since.getTime()))] : []
|
|
2148
2180
|
];
|
|
2149
2181
|
}
|
|
2182
|
+
var KNOWN_TRUST_TIERS = /* @__PURE__ */ new Set(["quarantined", "trusted"]);
|
|
2183
|
+
function normalizeTrustTier(value) {
|
|
2184
|
+
if (value === void 0 || value === null) return null;
|
|
2185
|
+
return KNOWN_TRUST_TIERS.has(value) ? value : null;
|
|
2186
|
+
}
|
|
2150
2187
|
async function mapInBatches(items, fn) {
|
|
2151
2188
|
const BATCH = 50;
|
|
2152
2189
|
const results = [];
|
|
@@ -2187,6 +2224,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
2187
2224
|
supersededBy: memory.supersededBy ?? null,
|
|
2188
2225
|
supersededAt: memory.supersededAt ?? null,
|
|
2189
2226
|
lastObservedAt: memory.lastObservedAt ?? null,
|
|
2227
|
+
factType: memory.factType ?? null,
|
|
2228
|
+
archivedAt: memory.archivedAt ?? null,
|
|
2229
|
+
trustTier: memory.trustTier ?? null,
|
|
2190
2230
|
createdAt: memory.createdAt,
|
|
2191
2231
|
updatedAt: memory.updatedAt,
|
|
2192
2232
|
isDeleted: memory.isDeleted
|
|
@@ -2228,6 +2268,12 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
2228
2268
|
record._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
2229
2269
|
record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
2230
2270
|
}
|
|
2271
|
+
if (opts.factType !== void 0) {
|
|
2272
|
+
record._setRaw("fact_type", opts.factType);
|
|
2273
|
+
}
|
|
2274
|
+
if (opts.trustTier !== void 0) {
|
|
2275
|
+
record._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
2276
|
+
}
|
|
2231
2277
|
});
|
|
2232
2278
|
});
|
|
2233
2279
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -2368,6 +2414,12 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
2368
2414
|
record._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
2369
2415
|
record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
2370
2416
|
}
|
|
2417
|
+
if (opts.factType !== void 0) {
|
|
2418
|
+
record._setRaw("fact_type", opts.factType);
|
|
2419
|
+
}
|
|
2420
|
+
if (opts.trustTier !== void 0) {
|
|
2421
|
+
record._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
2422
|
+
}
|
|
2371
2423
|
})
|
|
2372
2424
|
);
|
|
2373
2425
|
await ctx.database.batch(...prepared);
|
|
@@ -2428,6 +2480,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
2428
2480
|
supersededBy: raw.superseded_by ?? null,
|
|
2429
2481
|
supersededAt: raw.superseded_at ?? null,
|
|
2430
2482
|
lastObservedAt: raw.last_observed_at ?? null,
|
|
2483
|
+
factType: raw.fact_type ?? null,
|
|
2484
|
+
archivedAt: raw.archived_at ?? null,
|
|
2485
|
+
trustTier: raw.trust_tier ?? null,
|
|
2431
2486
|
createdAt: new Date(raw.created_at),
|
|
2432
2487
|
updatedAt: new Date(raw.updated_at),
|
|
2433
2488
|
isDeleted: raw.is_deleted === true || raw.is_deleted === 1
|
|
@@ -2445,6 +2500,7 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
2445
2500
|
...baseVaultConditions(ctx, options),
|
|
2446
2501
|
...options?.scopes?.length ? [Q3.where("scope", Q3.oneOf(options.scopes))] : [],
|
|
2447
2502
|
...options?.folderId !== void 0 ? [Q3.where("folder_id", options.folderId)] : [],
|
|
2503
|
+
...options?.factTypes?.length ? [Q3.where("fact_type", Q3.oneOf(options.factTypes))] : [],
|
|
2448
2504
|
Q3.sortBy(options?.since ? "updated_at" : "created_at", Q3.desc),
|
|
2449
2505
|
...options?.limit !== null && options?.limit !== void 0 && options.limit > 0 ? [Q3.take(options.limit)] : []
|
|
2450
2506
|
];
|
|
@@ -2466,6 +2522,14 @@ async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
|
2466
2522
|
return stored.content;
|
|
2467
2523
|
});
|
|
2468
2524
|
}
|
|
2525
|
+
async function countActiveVaultMemoriesOp(ctx) {
|
|
2526
|
+
return ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx)).fetchCount();
|
|
2527
|
+
}
|
|
2528
|
+
async function getActiveVaultMemoryIdsOp(ctx, ids) {
|
|
2529
|
+
if (ids.length === 0) return /* @__PURE__ */ new Set();
|
|
2530
|
+
const rows = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx), Q3.where("id", Q3.oneOf(ids))).unsafeFetchRaw();
|
|
2531
|
+
return new Set(rows.map((r) => r.id));
|
|
2532
|
+
}
|
|
2469
2533
|
async function updateVaultMemoryOp(ctx, id, opts) {
|
|
2470
2534
|
try {
|
|
2471
2535
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -2519,6 +2583,15 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
2519
2583
|
if (opts.lastObservedAt !== void 0) {
|
|
2520
2584
|
r._setRaw("last_observed_at", opts.lastObservedAt);
|
|
2521
2585
|
}
|
|
2586
|
+
if (opts.factType !== void 0) {
|
|
2587
|
+
r._setRaw("fact_type", opts.factType);
|
|
2588
|
+
}
|
|
2589
|
+
if (opts.trustTier !== void 0) {
|
|
2590
|
+
r._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
2591
|
+
}
|
|
2592
|
+
if (opts.restore) {
|
|
2593
|
+
r._setRaw("archived_at", null);
|
|
2594
|
+
}
|
|
2522
2595
|
if (opts.preserveUpdatedAt) {
|
|
2523
2596
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
2524
2597
|
}
|
|
@@ -2775,6 +2848,98 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
2775
2848
|
}
|
|
2776
2849
|
return records.length;
|
|
2777
2850
|
}
|
|
2851
|
+
function assertVaultScopeForSweep(ctx) {
|
|
2852
|
+
if (ctx.userId === void 0 && ctx.singleTenant !== true) {
|
|
2853
|
+
throw new Error(
|
|
2854
|
+
"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.)"
|
|
2855
|
+
);
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
async function getDecayCandidatesRawOp(ctx) {
|
|
2859
|
+
assertVaultScopeForSweep(ctx);
|
|
2860
|
+
const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true })).unsafeFetchRaw();
|
|
2861
|
+
return results.map((raw) => ({
|
|
2862
|
+
uniqueId: raw.id,
|
|
2863
|
+
factType: raw.fact_type ?? null,
|
|
2864
|
+
eventTimeEnd: raw.event_time_end ?? null,
|
|
2865
|
+
eventTimeKind: raw.event_time_kind ?? null,
|
|
2866
|
+
updatedAt: raw.updated_at,
|
|
2867
|
+
archivedAt: raw.archived_at ?? null,
|
|
2868
|
+
source: raw.source ?? null,
|
|
2869
|
+
trustTier: raw.trust_tier ?? null
|
|
2870
|
+
}));
|
|
2871
|
+
}
|
|
2872
|
+
async function archiveVaultMemoryOp(ctx, id, opts) {
|
|
2873
|
+
try {
|
|
2874
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
2875
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2876
|
+
let stale = false;
|
|
2877
|
+
const archivedAtValue = opts?.now ?? Date.now();
|
|
2878
|
+
await ctx.database.write(async () => {
|
|
2879
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
|
|
2880
|
+
stale = true;
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
if (opts?.expectedUpdatedAt !== void 0 && record.updatedAt.getTime() !== opts.expectedUpdatedAt) {
|
|
2884
|
+
stale = true;
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2887
|
+
await record.update((r) => {
|
|
2888
|
+
r._setRaw("archived_at", archivedAtValue);
|
|
2889
|
+
});
|
|
2890
|
+
});
|
|
2891
|
+
return !stale;
|
|
2892
|
+
} catch {
|
|
2893
|
+
return false;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
async function restoreVaultMemoryOp(ctx, id) {
|
|
2897
|
+
try {
|
|
2898
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
2899
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2900
|
+
let stale = false;
|
|
2901
|
+
await ctx.database.write(async () => {
|
|
2902
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
2903
|
+
stale = true;
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
await record.update((r) => {
|
|
2907
|
+
r._setRaw("archived_at", null);
|
|
2908
|
+
});
|
|
2909
|
+
});
|
|
2910
|
+
return !stale;
|
|
2911
|
+
} catch {
|
|
2912
|
+
return false;
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
async function hardDeleteDecayedOp(ctx, id, opts) {
|
|
2916
|
+
try {
|
|
2917
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
2918
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2919
|
+
const now = opts.now ?? Date.now();
|
|
2920
|
+
let stale = false;
|
|
2921
|
+
await ctx.database.write(async () => {
|
|
2922
|
+
const archivedAt = record.archivedAt;
|
|
2923
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
2924
|
+
stale = true;
|
|
2925
|
+
return;
|
|
2926
|
+
}
|
|
2927
|
+
await record.update((r) => {
|
|
2928
|
+
r._setRaw("is_deleted", true);
|
|
2929
|
+
});
|
|
2930
|
+
});
|
|
2931
|
+
if (stale) return false;
|
|
2932
|
+
if (ctx.entityCtx) {
|
|
2933
|
+
try {
|
|
2934
|
+
await unlinkMemoryEntitiesOp(ctx.entityCtx, [id]);
|
|
2935
|
+
} catch {
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
return true;
|
|
2939
|
+
} catch {
|
|
2940
|
+
return false;
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2778
2943
|
async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel) {
|
|
2779
2944
|
try {
|
|
2780
2945
|
const record = await ctx.vaultMemoryCollection.find(id);
|
|
@@ -2954,6 +3119,9 @@ async function withEmbeddingRetry(call) {
|
|
|
2954
3119
|
}
|
|
2955
3120
|
}
|
|
2956
3121
|
if (threw) throw lastThrown;
|
|
3122
|
+
if (last?.error instanceof Error && last.response?.status === void 0) {
|
|
3123
|
+
throw last.error;
|
|
3124
|
+
}
|
|
2957
3125
|
return last;
|
|
2958
3126
|
}
|
|
2959
3127
|
var EmbeddingHttpError = class extends Error {
|
|
@@ -3800,6 +3968,7 @@ function rankVaultMemories(_query, queryEmbedding, items, options) {
|
|
|
3800
3968
|
sourceChunkIds: item.sourceChunkIds,
|
|
3801
3969
|
eventTimeEnd: item.eventTimeEnd,
|
|
3802
3970
|
eventTimeKind: item.eventTimeKind,
|
|
3971
|
+
factType: item.factType,
|
|
3803
3972
|
similarity: cosineSimilarity(queryEmbedding, item.embedding)
|
|
3804
3973
|
}));
|
|
3805
3974
|
const filtered = scored.filter((r) => r.similarity >= minSimilarity);
|
|
@@ -3850,6 +4019,7 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
|
|
|
3850
4019
|
const recencyAlpha = options?.recencyAlpha ?? 1;
|
|
3851
4020
|
const proofCountAlpha = options?.proofCountAlpha ?? 0.1;
|
|
3852
4021
|
const bm25AdmissionDivisor = options?.bm25AdmissionDivisor ?? 50;
|
|
4022
|
+
const factTypeWeights = options?.factTypeWeights;
|
|
3853
4023
|
if (items.length === 0) return [];
|
|
3854
4024
|
const baseRanked = rankVaultMemories(query, queryEmbedding, items, {
|
|
3855
4025
|
limit: items.length,
|
|
@@ -3881,7 +4051,8 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
|
|
|
3881
4051
|
eventTimeStart: item.eventTimeStart,
|
|
3882
4052
|
sourceChunkIds: item.sourceChunkIds,
|
|
3883
4053
|
eventTimeEnd: item.eventTimeEnd,
|
|
3884
|
-
eventTimeKind: item.eventTimeKind
|
|
4054
|
+
eventTimeKind: item.eventTimeKind,
|
|
4055
|
+
factType: item.factType
|
|
3885
4056
|
});
|
|
3886
4057
|
}
|
|
3887
4058
|
const boostFor = (id) => {
|
|
@@ -3890,7 +4061,9 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
|
|
|
3890
4061
|
const recencyBoost = 1 + recencyAlpha * (recency - 0.5);
|
|
3891
4062
|
const proofCount = Math.max(1, item?.proofCount ?? 1);
|
|
3892
4063
|
const proofBoost = 1 + proofCountAlpha * Math.log(1 + proofCount) - proofCountAlpha * Math.log(2);
|
|
3893
|
-
|
|
4064
|
+
const rawTypeWeight = item?.factType ? factTypeWeights?.[item.factType] : void 0;
|
|
4065
|
+
const typeWeight = rawTypeWeight !== void 0 && Number.isFinite(rawTypeWeight) && rawTypeWeight > 0 ? rawTypeWeight : 1;
|
|
4066
|
+
return recencyBoost * proofBoost * typeWeight;
|
|
3894
4067
|
};
|
|
3895
4068
|
let combined = [...baseRanked, ...admitted].map((r) => ({
|
|
3896
4069
|
...r,
|
|
@@ -3942,7 +4115,8 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3942
4115
|
supersessionWindow: options?.supersessionWindow,
|
|
3943
4116
|
proofCountAlpha: options?.proofCountAlpha,
|
|
3944
4117
|
bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
|
|
3945
|
-
rrfK: options?.rrfK
|
|
4118
|
+
rrfK: options?.rrfK,
|
|
4119
|
+
...options?.factTypeWeights && { factTypeWeights: options.factTypeWeights }
|
|
3946
4120
|
});
|
|
3947
4121
|
if (options?.v2HeadStats) {
|
|
3948
4122
|
options.v2HeadStats.hadResults = v2Ranked.length > 0;
|
|
@@ -4035,7 +4209,8 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
4035
4209
|
eventTimeStart: orig?.eventTimeStart,
|
|
4036
4210
|
sourceChunkIds: orig?.sourceChunkIds,
|
|
4037
4211
|
eventTimeEnd: orig?.eventTimeEnd,
|
|
4038
|
-
eventTimeKind: orig?.eventTimeKind
|
|
4212
|
+
eventTimeKind: orig?.eventTimeKind,
|
|
4213
|
+
factType: orig?.factType
|
|
4039
4214
|
};
|
|
4040
4215
|
});
|
|
4041
4216
|
const remainingTail = combined.filter((r) => !pickedIds.has(r.uniqueId));
|
|
@@ -4061,7 +4236,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4061
4236
|
...options?.bm25AdmissionDivisor !== void 0 && {
|
|
4062
4237
|
bm25AdmissionDivisor: options.bm25AdmissionDivisor
|
|
4063
4238
|
},
|
|
4064
|
-
...options?.rrfK !== void 0 && { rrfK: options.rrfK }
|
|
4239
|
+
...options?.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
4240
|
+
...options?.factTypeWeights && { factTypeWeights: options.factTypeWeights }
|
|
4065
4241
|
};
|
|
4066
4242
|
const originalRanked = rankFusedVaultMemories(originalQuery, originalQueryEmbedding, items, {
|
|
4067
4243
|
limit: perFacetTopN,
|
|
@@ -4099,7 +4275,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4099
4275
|
eventTimeStart: item.eventTimeStart,
|
|
4100
4276
|
sourceChunkIds: item.sourceChunkIds,
|
|
4101
4277
|
eventTimeEnd: item.eventTimeEnd,
|
|
4102
|
-
eventTimeKind: item.eventTimeKind
|
|
4278
|
+
eventTimeKind: item.eventTimeKind,
|
|
4279
|
+
factType: item.factType
|
|
4103
4280
|
};
|
|
4104
4281
|
}
|
|
4105
4282
|
);
|
|
@@ -4123,7 +4300,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4123
4300
|
eventTimeStart: item.eventTimeStart,
|
|
4124
4301
|
sourceChunkIds: item.sourceChunkIds,
|
|
4125
4302
|
eventTimeEnd: item.eventTimeEnd,
|
|
4126
|
-
eventTimeKind: item.eventTimeKind
|
|
4303
|
+
eventTimeKind: item.eventTimeKind,
|
|
4304
|
+
factType: item.factType
|
|
4127
4305
|
});
|
|
4128
4306
|
}
|
|
4129
4307
|
}
|
|
@@ -4180,7 +4358,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4180
4358
|
eventTimeStart: orig?.eventTimeStart,
|
|
4181
4359
|
sourceChunkIds: orig?.sourceChunkIds,
|
|
4182
4360
|
eventTimeEnd: orig?.eventTimeEnd,
|
|
4183
|
-
eventTimeKind: orig?.eventTimeKind
|
|
4361
|
+
eventTimeKind: orig?.eventTimeKind,
|
|
4362
|
+
factType: orig?.factType
|
|
4184
4363
|
};
|
|
4185
4364
|
});
|
|
4186
4365
|
const remainingTail = combined.filter((r) => !pickedIds.has(r.uniqueId));
|
|
@@ -4252,6 +4431,8 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4252
4431
|
const queryOpts = {};
|
|
4253
4432
|
if (scopes?.length) queryOpts.scopes = scopes;
|
|
4254
4433
|
if (folderId !== void 0) queryOpts.folderId = folderId;
|
|
4434
|
+
if (searchOptions?.factTypes?.length) queryOpts.factTypes = searchOptions.factTypes;
|
|
4435
|
+
if (searchOptions?.includeArchived) queryOpts.includeArchived = true;
|
|
4255
4436
|
const loaded = await getAllVaultMemoriesOp(
|
|
4256
4437
|
vaultCtx,
|
|
4257
4438
|
Object.keys(queryOpts).length > 0 ? queryOpts : void 0
|
|
@@ -4323,7 +4504,8 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4323
4504
|
eventTimeStart: m.eventTimeStart,
|
|
4324
4505
|
sourceChunkIds: m.sourceChunkIds,
|
|
4325
4506
|
eventTimeEnd: m.eventTimeEnd,
|
|
4326
|
-
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind)
|
|
4507
|
+
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
4508
|
+
factType: m.factType
|
|
4327
4509
|
}));
|
|
4328
4510
|
if (queryEmbedding.length > 0) {
|
|
4329
4511
|
const mismatched = embeddedItems.filter(
|
|
@@ -4367,7 +4549,8 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4367
4549
|
...searchOptions?.bm25AdmissionDivisor !== void 0 && {
|
|
4368
4550
|
bm25AdmissionDivisor: searchOptions.bm25AdmissionDivisor
|
|
4369
4551
|
},
|
|
4370
|
-
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK }
|
|
4552
|
+
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
4553
|
+
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
4371
4554
|
};
|
|
4372
4555
|
if (useFusion && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
4373
4556
|
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
@@ -4534,7 +4717,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
4534
4717
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
4535
4718
|
);
|
|
4536
4719
|
}
|
|
4537
|
-
const { recall: recall2 } = await import("./recall-
|
|
4720
|
+
const { recall: recall2 } = await import("./recall-FZVV5XUU.mjs");
|
|
4538
4721
|
const result = await recall2(
|
|
4539
4722
|
query,
|
|
4540
4723
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
@@ -4645,6 +4828,159 @@ function extractQueryEntities(query) {
|
|
|
4645
4828
|
return [...seen];
|
|
4646
4829
|
}
|
|
4647
4830
|
|
|
4831
|
+
// src/lib/memory/graphTraversal.ts
|
|
4832
|
+
var MAX_HOPS = 2;
|
|
4833
|
+
var ENTITY_FANOUT = 8;
|
|
4834
|
+
var MIN_REFINER_CANDIDATES = 16;
|
|
4835
|
+
var MAX_REFINER_CANDIDATES = 64;
|
|
4836
|
+
var NODE_BUDGET = 64;
|
|
4837
|
+
var VAULT_SIZE_HOP_CAP = 1e3;
|
|
4838
|
+
function clampPositiveInt(value, fallback) {
|
|
4839
|
+
if (value === void 0 || !Number.isFinite(value) || value < 1) return fallback;
|
|
4840
|
+
return Math.floor(value);
|
|
4841
|
+
}
|
|
4842
|
+
function capHopsForDensity(maxHops, vaultSize) {
|
|
4843
|
+
if (vaultSize !== void 0 && vaultSize > VAULT_SIZE_HOP_CAP) return Math.min(maxHops, 1);
|
|
4844
|
+
return maxHops;
|
|
4845
|
+
}
|
|
4846
|
+
function rankMemoriesByOverlap(map) {
|
|
4847
|
+
return [...map.entries()].sort((a, b) => b[1].size - a[1].size).map(([memoryId]) => memoryId);
|
|
4848
|
+
}
|
|
4849
|
+
async function traverseGraphLane(query, entityCtx, options = {}) {
|
|
4850
|
+
const seedNames = extractQueryEntities(query);
|
|
4851
|
+
if (seedNames.length === 0) return [];
|
|
4852
|
+
const entityFanout = clampPositiveInt(options.entityFanout, ENTITY_FANOUT);
|
|
4853
|
+
const nodeBudget = clampPositiveInt(options.nodeBudget, NODE_BUDGET);
|
|
4854
|
+
const maxHops = capHopsForDensity(clampPositiveInt(options.maxHops, MAX_HOPS), options.vaultSize);
|
|
4855
|
+
const keepActive = async (map) => {
|
|
4856
|
+
if (!options.filterActiveMemoryIds || map.size === 0) return map;
|
|
4857
|
+
const active = await options.filterActiveMemoryIds([...map.keys()]);
|
|
4858
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
4859
|
+
for (const [id, names] of map) if (active.has(id)) filtered.set(id, names);
|
|
4860
|
+
return filtered;
|
|
4861
|
+
};
|
|
4862
|
+
const hop1 = await keepActive(await getMemoriesByEntityNamesOp(entityCtx, seedNames));
|
|
4863
|
+
if (hop1.size === 0) return [];
|
|
4864
|
+
const hop1Ranking = rankMemoriesByOverlap(hop1);
|
|
4865
|
+
if (maxHops <= 1) return hop1Ranking;
|
|
4866
|
+
const hop1Emitted = hop1Ranking.slice(0, nodeBudget);
|
|
4867
|
+
const perHopRankings = [hop1Emitted];
|
|
4868
|
+
const firstHopOf = /* @__PURE__ */ new Map();
|
|
4869
|
+
for (const id of hop1Emitted) if (!firstHopOf.has(id)) firstHopOf.set(id, 1);
|
|
4870
|
+
const accumulated = new Set(hop1Emitted);
|
|
4871
|
+
const seenEntities = new Set(seedNames);
|
|
4872
|
+
let frontier = hop1Emitted;
|
|
4873
|
+
for (let hop = 2; hop <= maxHops; hop++) {
|
|
4874
|
+
if (frontier.length === 0) break;
|
|
4875
|
+
if (accumulated.size >= nodeBudget) break;
|
|
4876
|
+
const memoryToEntities = await getEntitiesByMemoryIdsOp(entityCtx, frontier);
|
|
4877
|
+
const neighborCounts = /* @__PURE__ */ new Map();
|
|
4878
|
+
for (const names of memoryToEntities.values()) {
|
|
4879
|
+
for (const name of names) {
|
|
4880
|
+
if (seenEntities.has(name)) continue;
|
|
4881
|
+
neighborCounts.set(name, (neighborCounts.get(name) ?? 0) + 1);
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
if (neighborCounts.size === 0) break;
|
|
4885
|
+
const rankedNeighbors = [...neighborCounts.entries()].sort((a, b) => b[1] - a[1]).map(([name]) => name);
|
|
4886
|
+
let topNeighbors = rankedNeighbors.slice(0, entityFanout);
|
|
4887
|
+
if (options.refineNeighbors && rankedNeighbors.length > entityFanout) {
|
|
4888
|
+
try {
|
|
4889
|
+
const refinerCandidateCap = Math.min(
|
|
4890
|
+
Math.max(entityFanout * 2, MIN_REFINER_CANDIDATES),
|
|
4891
|
+
MAX_REFINER_CANDIDATES
|
|
4892
|
+
);
|
|
4893
|
+
const refinerCandidates = rankedNeighbors.slice(0, refinerCandidateCap);
|
|
4894
|
+
const refined = await options.refineNeighbors.refine(
|
|
4895
|
+
query,
|
|
4896
|
+
refinerCandidates,
|
|
4897
|
+
entityFanout
|
|
4898
|
+
);
|
|
4899
|
+
const valid = [];
|
|
4900
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4901
|
+
for (const name of refined) {
|
|
4902
|
+
if (!neighborCounts.has(name) || seen.has(name)) continue;
|
|
4903
|
+
seen.add(name);
|
|
4904
|
+
valid.push(name);
|
|
4905
|
+
if (valid.length >= entityFanout) break;
|
|
4906
|
+
}
|
|
4907
|
+
if (valid.length > 0) topNeighbors = valid;
|
|
4908
|
+
} catch (err) {
|
|
4909
|
+
getLogger().warn(
|
|
4910
|
+
`[memory/graph] neighbor refine failed; using co-occurrence order: ${err instanceof Error ? err.message : String(err)}`
|
|
4911
|
+
);
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
for (const name of topNeighbors) seenEntities.add(name);
|
|
4915
|
+
const hopMap = await keepActive(await getMemoriesByEntityNamesOp(entityCtx, topNeighbors));
|
|
4916
|
+
if (hopMap.size === 0) break;
|
|
4917
|
+
const hopRanking = rankMemoriesByOverlap(hopMap);
|
|
4918
|
+
const newlyDiscovered = [];
|
|
4919
|
+
for (const id of hopRanking) {
|
|
4920
|
+
if (accumulated.has(id)) continue;
|
|
4921
|
+
accumulated.add(id);
|
|
4922
|
+
newlyDiscovered.push(id);
|
|
4923
|
+
firstHopOf.set(id, hop);
|
|
4924
|
+
if (accumulated.size >= nodeBudget) break;
|
|
4925
|
+
}
|
|
4926
|
+
if (newlyDiscovered.length === 0) break;
|
|
4927
|
+
perHopRankings.push(newlyDiscovered);
|
|
4928
|
+
frontier = newlyDiscovered;
|
|
4929
|
+
}
|
|
4930
|
+
const fused = rrfFuse(perHopRankings, options.rrfK);
|
|
4931
|
+
return [...fused.entries()].sort((a, b) => {
|
|
4932
|
+
const hopA = firstHopOf.get(a[0]) ?? Infinity;
|
|
4933
|
+
const hopB = firstHopOf.get(b[0]) ?? Infinity;
|
|
4934
|
+
if (hopA !== hopB) return hopA - hopB;
|
|
4935
|
+
return b[1] - a[1];
|
|
4936
|
+
}).map(([id]) => id);
|
|
4937
|
+
}
|
|
4938
|
+
var DEFAULT_REFINER_MODEL = "inclusionai/ling-2.6-flash";
|
|
4939
|
+
var DEFAULT_REFINER_ATTEMPTS = 1;
|
|
4940
|
+
var DEFAULT_REFINER_TOTAL_TIMEOUT_MS = 8e3;
|
|
4941
|
+
function createLlmNeighborRefiner(options) {
|
|
4942
|
+
return {
|
|
4943
|
+
async refine(query, candidates, limit) {
|
|
4944
|
+
if (candidates.length === 0) return [];
|
|
4945
|
+
const numbered = candidates.map((name, i) => `[${i + 1}] ${name}`).join("\n");
|
|
4946
|
+
const systemPrompt = `You help a memory-retrieval system decide which related topics to explore.
|
|
4947
|
+
|
|
4948
|
+
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.
|
|
4949
|
+
|
|
4950
|
+
Output strict JSON, no prose: { "expand": [<entity names to expand, verbatim from the list>] }`;
|
|
4951
|
+
const parsed = await callPortalJsonCompletion({
|
|
4952
|
+
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
4953
|
+
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
4954
|
+
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
4955
|
+
model: options.model ?? DEFAULT_REFINER_MODEL,
|
|
4956
|
+
systemPrompt,
|
|
4957
|
+
userMessage: `Question: ${query}
|
|
4958
|
+
|
|
4959
|
+
Candidate topics:
|
|
4960
|
+
${numbered}
|
|
4961
|
+
|
|
4962
|
+
Which should be expanded?`,
|
|
4963
|
+
tag: "memory/graph-refine",
|
|
4964
|
+
maxAttempts: options.maxAttempts ?? DEFAULT_REFINER_ATTEMPTS,
|
|
4965
|
+
totalTimeoutMs: options.totalTimeoutMs ?? DEFAULT_REFINER_TOTAL_TIMEOUT_MS,
|
|
4966
|
+
...options.backoffMs && { backoffMs: options.backoffMs },
|
|
4967
|
+
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
4968
|
+
});
|
|
4969
|
+
if (parsed === null || typeof parsed !== "object") return [];
|
|
4970
|
+
const list = parsed.expand;
|
|
4971
|
+
if (!Array.isArray(list)) return [];
|
|
4972
|
+
const byNormalized = new Map(candidates.map((c) => [normalizeEntityName(c), c]));
|
|
4973
|
+
const out = [];
|
|
4974
|
+
for (const raw of list) {
|
|
4975
|
+
if (typeof raw !== "string") continue;
|
|
4976
|
+
const match = byNormalized.get(normalizeEntityName(raw));
|
|
4977
|
+
if (match) out.push(match);
|
|
4978
|
+
}
|
|
4979
|
+
return out;
|
|
4980
|
+
}
|
|
4981
|
+
};
|
|
4982
|
+
}
|
|
4983
|
+
|
|
4648
4984
|
// src/lib/memory/queryTemporal.ts
|
|
4649
4985
|
var RELATIVE_DAY_ENTRIES = [
|
|
4650
4986
|
[/\btoday\b/, "today", 0],
|
|
@@ -4857,12 +5193,12 @@ var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
|
4857
5193
|
function flagsForBudget(budget) {
|
|
4858
5194
|
switch (budget) {
|
|
4859
5195
|
case "high":
|
|
4860
|
-
return { rerank: true, decompose: true };
|
|
5196
|
+
return { rerank: true, decompose: true, traverse: true };
|
|
4861
5197
|
case "mid":
|
|
4862
|
-
return { rerank: true, decompose: false };
|
|
5198
|
+
return { rerank: true, decompose: false, traverse: false };
|
|
4863
5199
|
case "low":
|
|
4864
5200
|
default:
|
|
4865
|
-
return { rerank: false, decompose: false };
|
|
5201
|
+
return { rerank: false, decompose: false, traverse: false };
|
|
4866
5202
|
}
|
|
4867
5203
|
}
|
|
4868
5204
|
function dedupeBy(items, ...keys) {
|
|
@@ -4930,11 +5266,25 @@ async function recall(query, ctx, options = {}) {
|
|
|
4930
5266
|
}
|
|
4931
5267
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
4932
5268
|
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
5269
|
+
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
4933
5270
|
const prepStart = nowMs();
|
|
4934
5271
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
4935
5272
|
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
|
|
4936
|
-
|
|
4937
|
-
|
|
5273
|
+
// The graph + temporal lanes are AUXILIARY (RRF side-signals). A transient
|
|
5274
|
+
// WatermelonDB throw in either must NOT reject this Promise.all and take
|
|
5275
|
+
// PRIMARY cosine/BM25 recall down with it — degrade the failing lane to an
|
|
5276
|
+
// empty ranking instead (mirrors safeCountVault's fail-soft posture).
|
|
5277
|
+
safeLane(
|
|
5278
|
+
"graph",
|
|
5279
|
+
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
5280
|
+
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
5281
|
+
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
5282
|
+
...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
|
|
5283
|
+
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
5284
|
+
...graphRefiner && { refineNeighbors: graphRefiner }
|
|
5285
|
+
})
|
|
5286
|
+
),
|
|
5287
|
+
wantsTemporal ? safeLane("temporal", () => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)) : Promise.resolve([])
|
|
4938
5288
|
]);
|
|
4939
5289
|
prepMs = nowMs() - prepStart;
|
|
4940
5290
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
@@ -4984,6 +5334,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
4984
5334
|
},
|
|
4985
5335
|
...options.scopes && { scopes: options.scopes },
|
|
4986
5336
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
5337
|
+
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
5338
|
+
...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
|
|
4987
5339
|
...entityRanking.length > 0 && { entityRanking },
|
|
4988
5340
|
...temporalRanking.length > 0 && { temporalRanking }
|
|
4989
5341
|
}
|
|
@@ -5105,6 +5457,9 @@ function toFactMemory(r) {
|
|
|
5105
5457
|
...r.eventTimeStart !== void 0 && { eventTimeStart: r.eventTimeStart },
|
|
5106
5458
|
...r.eventTimeEnd !== void 0 && { eventTimeEnd: r.eventTimeEnd },
|
|
5107
5459
|
...r.eventTimeKind !== void 0 && { eventTimeKind: r.eventTimeKind },
|
|
5460
|
+
// Typed memory (PR1) — surfaced from VaultSearchResult so recall results
|
|
5461
|
+
// (and UI reading them) carry the fact's type. Undefined when untyped.
|
|
5462
|
+
...r.factType !== void 0 && { factType: r.factType },
|
|
5108
5463
|
...r.sourceChunkIds !== void 0 && r.sourceChunkIds !== null && { sourceChunkIds: r.sourceChunkIds },
|
|
5109
5464
|
// r.similarity from searchVaultMemoriesWithSize is the fused score
|
|
5110
5465
|
// (cosine + BM25 + RRF + recency + proof) when useFusion=true (the
|
|
@@ -5118,14 +5473,47 @@ function toFactMemory(r) {
|
|
|
5118
5473
|
updatedAt: r.updatedAt ?? /* @__PURE__ */ new Date(0)
|
|
5119
5474
|
};
|
|
5120
5475
|
}
|
|
5121
|
-
async function buildGraphLaneRanking(query, ctx) {
|
|
5476
|
+
async function buildGraphLaneRanking(query, ctx, traverse = false, traversalOptions = {}) {
|
|
5122
5477
|
const entityCtx = ctx.entityCtx ?? ctx.vaultCtx?.entityCtx;
|
|
5123
5478
|
if (!entityCtx) return [];
|
|
5479
|
+
if (traverse) {
|
|
5480
|
+
const vaultSize = await safeCountVault(ctx);
|
|
5481
|
+
const vaultCtx2 = ctx.vaultCtx;
|
|
5482
|
+
return traverseGraphLane(query, entityCtx, {
|
|
5483
|
+
...traversalOptions,
|
|
5484
|
+
...vaultSize !== void 0 && { vaultSize },
|
|
5485
|
+
...vaultCtx2 && {
|
|
5486
|
+
filterActiveMemoryIds: (ids) => getActiveVaultMemoryIdsOp(vaultCtx2, ids)
|
|
5487
|
+
}
|
|
5488
|
+
});
|
|
5489
|
+
}
|
|
5124
5490
|
const queryEntities = extractQueryEntities(query);
|
|
5125
5491
|
if (queryEntities.length === 0) return [];
|
|
5126
5492
|
const memoryToEntities = await getMemoriesByEntityNamesOp(entityCtx, queryEntities);
|
|
5127
5493
|
if (memoryToEntities.size === 0) return [];
|
|
5128
|
-
|
|
5494
|
+
const ranked = [...memoryToEntities.entries()].sort((a, b) => b[1].size - a[1].size).map(([memoryId]) => memoryId);
|
|
5495
|
+
const vaultCtx = ctx.vaultCtx;
|
|
5496
|
+
if (!vaultCtx) return ranked;
|
|
5497
|
+
const activeIds = await getActiveVaultMemoryIdsOp(vaultCtx, ranked);
|
|
5498
|
+
return ranked.filter((id) => activeIds.has(id));
|
|
5499
|
+
}
|
|
5500
|
+
async function safeCountVault(ctx) {
|
|
5501
|
+
if (!ctx.vaultCtx) return void 0;
|
|
5502
|
+
try {
|
|
5503
|
+
return await countActiveVaultMemoriesOp(ctx.vaultCtx);
|
|
5504
|
+
} catch {
|
|
5505
|
+
return void 0;
|
|
5506
|
+
}
|
|
5507
|
+
}
|
|
5508
|
+
async function safeLane(label, run) {
|
|
5509
|
+
try {
|
|
5510
|
+
return await run();
|
|
5511
|
+
} catch (err) {
|
|
5512
|
+
getLogger().warn(
|
|
5513
|
+
`[memory/recall] ${label} lane failed; continuing without it: ${err instanceof Error ? err.message : String(err)}`
|
|
5514
|
+
);
|
|
5515
|
+
return [];
|
|
5516
|
+
}
|
|
5129
5517
|
}
|
|
5130
5518
|
async function buildTemporalLaneRanking(query, vaultCtx, now) {
|
|
5131
5519
|
const window2 = parseQueryTimeWindow(query, now);
|
|
@@ -5239,6 +5627,7 @@ export {
|
|
|
5239
5627
|
replaceMemoryEntitiesGuardedOp,
|
|
5240
5628
|
backfillMemoryEntityUserIdsOp,
|
|
5241
5629
|
getMemoriesByEntityNamesOp,
|
|
5630
|
+
getEntitiesByMemoryIdsOp,
|
|
5242
5631
|
vaultMemoryToStored,
|
|
5243
5632
|
createVaultMemoryOp,
|
|
5244
5633
|
createSupersedingMemoryOp,
|
|
@@ -5256,12 +5645,24 @@ export {
|
|
|
5256
5645
|
getMemoriesNeedingTopicExtractionOp,
|
|
5257
5646
|
stampTopicsExtractedAtOp,
|
|
5258
5647
|
deleteAllVaultMemoriesForUserOp,
|
|
5648
|
+
assertVaultScopeForSweep,
|
|
5649
|
+
getDecayCandidatesRawOp,
|
|
5650
|
+
archiveVaultMemoryOp,
|
|
5651
|
+
restoreVaultMemoryOp,
|
|
5652
|
+
hardDeleteDecayedOp,
|
|
5259
5653
|
updateVaultMemoryEmbeddingOp,
|
|
5260
5654
|
RerankerUnavailableError,
|
|
5261
5655
|
isRerankerAvailable,
|
|
5262
5656
|
DEFAULT_VAULT_CACHE_SIZE,
|
|
5263
5657
|
LRUCache,
|
|
5264
5658
|
createVaultEmbeddingCache,
|
|
5659
|
+
MAX_HOPS,
|
|
5660
|
+
ENTITY_FANOUT,
|
|
5661
|
+
NODE_BUDGET,
|
|
5662
|
+
VAULT_SIZE_HOP_CAP,
|
|
5663
|
+
capHopsForDensity,
|
|
5664
|
+
traverseGraphLane,
|
|
5665
|
+
createLlmNeighborRefiner,
|
|
5265
5666
|
recall,
|
|
5266
5667
|
preEmbedVaultMemories,
|
|
5267
5668
|
eagerEmbedContent,
|