@anuma/sdk 3.3.1 → 3.5.0
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-EIHIZ5L4.mjs → chunk-7TATXBC5.mjs} +123 -16
- package/dist/expo/index.cjs +158 -22
- package/dist/expo/index.d.mts +70 -1
- package/dist/expo/index.d.ts +70 -1
- package/dist/expo/index.mjs +27 -3
- package/dist/expo/{recall-C3LJ5R2E.mjs → recall-IO4KJ5W7.mjs} +1 -1
- package/dist/react/{chunk-PWTWECXY.mjs → chunk-DDHTJGZN.mjs} +123 -16
- package/dist/react/index.cjs +158 -22
- package/dist/react/index.d.mts +70 -1
- package/dist/react/index.d.ts +70 -1
- package/dist/react/index.mjs +27 -3
- package/dist/react/{recall-FZVV5XUU.mjs → recall-OPKHWKZX.mjs} +1 -1
- package/dist/server/{chunk-J5QZOPUI.mjs → chunk-V7SVKIXQ.mjs} +123 -16
- package/dist/server/index.cjs +158 -22
- package/dist/server/index.d.mts +70 -1
- package/dist/server/index.d.ts +70 -1
- package/dist/server/index.mjs +27 -3
- package/dist/server/{recall-NNBMWRLB.mjs → recall-IWY2MYHR.mjs} +1 -1
- package/package.json +1 -1
|
@@ -3357,11 +3357,20 @@ async function getModel() {
|
|
|
3357
3357
|
function sigmoid(x) {
|
|
3358
3358
|
return 1 / (1 + Math.exp(-x));
|
|
3359
3359
|
}
|
|
3360
|
+
function formatRerankDoc(content, dateMs) {
|
|
3361
|
+
if (dateMs === null || dateMs === void 0 || !Number.isFinite(dateMs)) return content;
|
|
3362
|
+
const d = new Date(dateMs);
|
|
3363
|
+
if (!Number.isFinite(d.getTime())) return content;
|
|
3364
|
+
const yyyy = d.getFullYear();
|
|
3365
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
3366
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
3367
|
+
return `[Date: ${yyyy}-${mm}-${dd}] ${content}`;
|
|
3368
|
+
}
|
|
3360
3369
|
async function rerankPairs(query, items) {
|
|
3361
3370
|
if (items.length === 0 || !query) return [];
|
|
3362
3371
|
const { tokenizer, model } = await getModel();
|
|
3363
3372
|
const queries = items.map(() => query);
|
|
3364
|
-
const docs = items.map((i) => i.content);
|
|
3373
|
+
const docs = items.map((i) => formatRerankDoc(i.content, i.dateMs));
|
|
3365
3374
|
const tokenize2 = tokenizer;
|
|
3366
3375
|
const inputs = tokenize2(queries, { text_pair: docs, padding: true, truncation: true });
|
|
3367
3376
|
const forward = model;
|
|
@@ -3710,6 +3719,23 @@ function createVaultEmbeddingCache(maxSize = DEFAULT_VAULT_CACHE_SIZE) {
|
|
|
3710
3719
|
function normalizeEventTimeKind(kind) {
|
|
3711
3720
|
return kind === "point" || kind === "range" || kind === "ongoing" ? kind : null;
|
|
3712
3721
|
}
|
|
3722
|
+
function rerankDateMs(item) {
|
|
3723
|
+
if (item.eventTimeStart !== null && item.eventTimeStart !== void 0 && Number.isFinite(item.eventTimeStart) && item.eventTimeStart > 0) {
|
|
3724
|
+
return item.eventTimeStart;
|
|
3725
|
+
}
|
|
3726
|
+
if (item.lastObservedAt !== null && item.lastObservedAt !== void 0 && Number.isFinite(item.lastObservedAt) && item.lastObservedAt > 0) {
|
|
3727
|
+
return item.lastObservedAt;
|
|
3728
|
+
}
|
|
3729
|
+
const updatedMs = item.updatedAt?.getTime();
|
|
3730
|
+
if (updatedMs !== null && updatedMs !== void 0 && Number.isFinite(updatedMs) && updatedMs > 0) {
|
|
3731
|
+
return updatedMs;
|
|
3732
|
+
}
|
|
3733
|
+
const createdMs = item.createdAt?.getTime();
|
|
3734
|
+
if (createdMs !== null && createdMs !== void 0 && Number.isFinite(createdMs) && createdMs > 0) {
|
|
3735
|
+
return createdMs;
|
|
3736
|
+
}
|
|
3737
|
+
return void 0;
|
|
3738
|
+
}
|
|
3713
3739
|
var SUPERSESSION_SIMILARITY_THRESHOLD = 0.7;
|
|
3714
3740
|
var SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
3715
3741
|
var SUPERSESSION_BOOST_FACTOR = 0.8;
|
|
@@ -3916,6 +3942,7 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3916
3942
|
}
|
|
3917
3943
|
let combined;
|
|
3918
3944
|
let tailSlice = [];
|
|
3945
|
+
const itemById = new Map(items.map((i) => [i.id, i]));
|
|
3919
3946
|
if (options?.rerank) {
|
|
3920
3947
|
const rerankTopN = options.rerankTopN ?? 30;
|
|
3921
3948
|
const ceWeight = options.ceWeight ?? 0.1;
|
|
@@ -3923,7 +3950,12 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3923
3950
|
try {
|
|
3924
3951
|
const reranked = await rerankPairs(
|
|
3925
3952
|
query,
|
|
3926
|
-
headSlice.map((r) => ({
|
|
3953
|
+
headSlice.map((r) => ({
|
|
3954
|
+
id: r.uniqueId,
|
|
3955
|
+
content: r.content,
|
|
3956
|
+
// C4: date-prefix the CE doc so temporal alignment influences rank.
|
|
3957
|
+
dateMs: rerankDateMs(itemById.get(r.uniqueId) ?? r)
|
|
3958
|
+
}))
|
|
3927
3959
|
);
|
|
3928
3960
|
tailSlice = v2Ranked.slice(rerankTopN);
|
|
3929
3961
|
const v2ScoreById = new Map(headSlice.map((r) => [r.uniqueId, r.similarity]));
|
|
@@ -3958,11 +3990,11 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3958
3990
|
const fused = rrfFuse([headIds, headIds, ...sideLanesAsync], options?.rrfK);
|
|
3959
3991
|
const fusedHead = combined.map((r) => ({ ...r, similarity: fused.get(r.uniqueId) ?? r.similarity })).sort((a, b) => b.similarity - a.similarity);
|
|
3960
3992
|
const seen = new Set(combined.map((r) => r.uniqueId));
|
|
3961
|
-
const
|
|
3993
|
+
const itemById2 = new Map(items.map((i) => [i.id, i]));
|
|
3962
3994
|
for (const lane of sideLanesAsync) {
|
|
3963
3995
|
for (const id of lane) {
|
|
3964
3996
|
if (seen.has(id)) continue;
|
|
3965
|
-
const it =
|
|
3997
|
+
const it = itemById2.get(id);
|
|
3966
3998
|
if (!it) continue;
|
|
3967
3999
|
fusedHead.push({
|
|
3968
4000
|
uniqueId: id,
|
|
@@ -3981,11 +4013,11 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
3981
4013
|
if (options?.mmr) {
|
|
3982
4014
|
const lambda = options.mmrLambda ?? 0.7;
|
|
3983
4015
|
const mmrTopN = options.mmrTopN ?? 20;
|
|
3984
|
-
const
|
|
4016
|
+
const itemById2 = new Map(items.map((i) => [i.id, i]));
|
|
3985
4017
|
const mmrCandidates = combined.slice(0, mmrTopN).map((r) => ({
|
|
3986
4018
|
id: r.uniqueId,
|
|
3987
4019
|
score: r.similarity,
|
|
3988
|
-
embedding:
|
|
4020
|
+
embedding: itemById2.get(r.uniqueId)?.embedding ?? [],
|
|
3989
4021
|
content: r.content
|
|
3990
4022
|
}));
|
|
3991
4023
|
const picked = applyMMR(mmrCandidates, limit, lambda);
|
|
@@ -4107,7 +4139,12 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4107
4139
|
try {
|
|
4108
4140
|
const reranked = await rerankPairs(
|
|
4109
4141
|
originalQuery,
|
|
4110
|
-
headSlice.map((r) => ({
|
|
4142
|
+
headSlice.map((r) => ({
|
|
4143
|
+
id: r.uniqueId,
|
|
4144
|
+
content: r.content,
|
|
4145
|
+
// C4: date-prefix the CE doc so temporal alignment influences rank.
|
|
4146
|
+
dateMs: rerankDateMs(itemById.get(r.uniqueId) ?? r)
|
|
4147
|
+
}))
|
|
4111
4148
|
);
|
|
4112
4149
|
const ceById = new Map(reranked.map((r) => [r.id, r.score]));
|
|
4113
4150
|
const head = headSlice.map((r) => ({
|
|
@@ -4294,6 +4331,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4294
4331
|
createdAt: m.createdAt,
|
|
4295
4332
|
updatedAt: m.updatedAt,
|
|
4296
4333
|
proofCount: m.proofCount,
|
|
4334
|
+
lastObservedAt: m.lastObservedAt,
|
|
4297
4335
|
eventTimeStart: m.eventTimeStart,
|
|
4298
4336
|
sourceChunkIds: m.sourceChunkIds,
|
|
4299
4337
|
eventTimeEnd: m.eventTimeEnd,
|
|
@@ -4310,13 +4348,27 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4310
4348
|
);
|
|
4311
4349
|
}
|
|
4312
4350
|
}
|
|
4313
|
-
const
|
|
4314
|
-
memories.map((m) => [
|
|
4351
|
+
const metaById = new Map(
|
|
4352
|
+
memories.map((m) => [
|
|
4353
|
+
m.uniqueId,
|
|
4354
|
+
{
|
|
4355
|
+
createdAt: m.createdAt,
|
|
4356
|
+
updatedAt: m.updatedAt,
|
|
4357
|
+
proofCount: m.proofCount,
|
|
4358
|
+
lastObservedAt: m.lastObservedAt
|
|
4359
|
+
}
|
|
4360
|
+
])
|
|
4315
4361
|
);
|
|
4316
4362
|
const stampTimestamps = (out) => {
|
|
4317
4363
|
const results2 = out.results.map((r) => {
|
|
4318
|
-
const
|
|
4319
|
-
return
|
|
4364
|
+
const meta = metaById.get(r.uniqueId);
|
|
4365
|
+
return meta ? {
|
|
4366
|
+
...r,
|
|
4367
|
+
createdAt: meta.createdAt,
|
|
4368
|
+
updatedAt: meta.updatedAt,
|
|
4369
|
+
proofCount: meta.proofCount,
|
|
4370
|
+
lastObservedAt: meta.lastObservedAt
|
|
4371
|
+
} : r;
|
|
4320
4372
|
});
|
|
4321
4373
|
return {
|
|
4322
4374
|
results: results2,
|
|
@@ -4510,7 +4562,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
4510
4562
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
4511
4563
|
);
|
|
4512
4564
|
}
|
|
4513
|
-
const { recall: recall2 } = await import("./recall-
|
|
4565
|
+
const { recall: recall2 } = await import("./recall-IO4KJ5W7.mjs");
|
|
4514
4566
|
const result = await recall2(
|
|
4515
4567
|
query,
|
|
4516
4568
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
@@ -4774,6 +4826,42 @@ Which should be expanded?`,
|
|
|
4774
4826
|
};
|
|
4775
4827
|
}
|
|
4776
4828
|
|
|
4829
|
+
// src/lib/memory/observationTrend.ts
|
|
4830
|
+
var DAY_MS2 = 1e3 * 60 * 60 * 24;
|
|
4831
|
+
var TREND_RECENT_WINDOW_DAYS = 30;
|
|
4832
|
+
var TREND_STALE_WINDOW_DAYS = 90;
|
|
4833
|
+
function toMs(value) {
|
|
4834
|
+
return value instanceof Date ? value.getTime() : value;
|
|
4835
|
+
}
|
|
4836
|
+
function classifyObservationTrend(input, now = Date.now()) {
|
|
4837
|
+
const createdMs = toMs(input.createdAt);
|
|
4838
|
+
if (!Number.isFinite(createdMs) || !Number.isFinite(now)) return "stable";
|
|
4839
|
+
const lastMsRaw = input.lastObservedAt;
|
|
4840
|
+
const lastMs = lastMsRaw !== null && lastMsRaw !== void 0 && Number.isFinite(lastMsRaw) ? Math.max(createdMs, lastMsRaw) : createdMs;
|
|
4841
|
+
const proofs = Math.max(1, input.proofCount ?? 1);
|
|
4842
|
+
const ageDays = Math.max(0, (now - createdMs) / DAY_MS2);
|
|
4843
|
+
const daysSinceLast = Math.max(0, (now - lastMs) / DAY_MS2);
|
|
4844
|
+
if (daysSinceLast >= TREND_STALE_WINDOW_DAYS) return "stale";
|
|
4845
|
+
if (daysSinceLast >= TREND_RECENT_WINDOW_DAYS) return "weakening";
|
|
4846
|
+
if (ageDays <= TREND_RECENT_WINDOW_DAYS && proofs <= 2) return "new";
|
|
4847
|
+
if (proofs >= 3) return "strengthening";
|
|
4848
|
+
if (proofs >= 2 && ageDays > TREND_RECENT_WINDOW_DAYS) return "strengthening";
|
|
4849
|
+
return "stable";
|
|
4850
|
+
}
|
|
4851
|
+
function summarizeObservationTrends(inputs, now = Date.now()) {
|
|
4852
|
+
const counts = {
|
|
4853
|
+
new: 0,
|
|
4854
|
+
strengthening: 0,
|
|
4855
|
+
stable: 0,
|
|
4856
|
+
weakening: 0,
|
|
4857
|
+
stale: 0
|
|
4858
|
+
};
|
|
4859
|
+
for (const input of inputs) {
|
|
4860
|
+
counts[classifyObservationTrend(input, now)]++;
|
|
4861
|
+
}
|
|
4862
|
+
return counts;
|
|
4863
|
+
}
|
|
4864
|
+
|
|
4777
4865
|
// src/lib/memory/queryTemporal.ts
|
|
4778
4866
|
var RELATIVE_DAY_ENTRIES = [
|
|
4779
4867
|
[/\btoday\b/, "today", 0],
|
|
@@ -5168,7 +5256,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
5168
5256
|
const fuseStart = nowMs();
|
|
5169
5257
|
if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
|
|
5170
5258
|
const memories2 = [
|
|
5171
|
-
...factResults.map(toFactMemory),
|
|
5259
|
+
...factResults.map((r) => toFactMemory(r, options.now)),
|
|
5172
5260
|
...chunkResults.map(toChunkMemory)
|
|
5173
5261
|
];
|
|
5174
5262
|
memories2.sort((a, b) => b.score - a.score);
|
|
@@ -5189,7 +5277,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
5189
5277
|
const fused = rrfFuse([factRanking, chunkRanking], options.rrfK);
|
|
5190
5278
|
const byId = /* @__PURE__ */ new Map();
|
|
5191
5279
|
for (const r of factResults) {
|
|
5192
|
-
const m = toFactMemory(r);
|
|
5280
|
+
const m = toFactMemory(r, options.now);
|
|
5193
5281
|
m.score = fused.get(`fact:${r.uniqueId}`) ?? 0;
|
|
5194
5282
|
if (!m.scoreBreakdown) m.scoreBreakdown = {};
|
|
5195
5283
|
m.scoreBreakdown.fused = r.similarity;
|
|
@@ -5238,7 +5326,10 @@ async function recall(query, ctx, options = {}) {
|
|
|
5238
5326
|
...vaultSize !== void 0 && { vaultSize }
|
|
5239
5327
|
};
|
|
5240
5328
|
}
|
|
5241
|
-
function toFactMemory(r) {
|
|
5329
|
+
function toFactMemory(r, now) {
|
|
5330
|
+
const createdAt = r.createdAt ?? /* @__PURE__ */ new Date(0);
|
|
5331
|
+
const proofCount = r.proofCount ?? void 0;
|
|
5332
|
+
const lastObservedAt = r.lastObservedAt ?? null;
|
|
5242
5333
|
return {
|
|
5243
5334
|
id: r.uniqueId,
|
|
5244
5335
|
kind: "fact",
|
|
@@ -5254,6 +5345,18 @@ function toFactMemory(r) {
|
|
|
5254
5345
|
// (and UI reading them) carry the fact's type. Undefined when untyped.
|
|
5255
5346
|
...r.factType !== void 0 && { factType: r.factType },
|
|
5256
5347
|
...r.sourceChunkIds !== void 0 && r.sourceChunkIds !== null && { sourceChunkIds: r.sourceChunkIds },
|
|
5348
|
+
...proofCount !== void 0 && proofCount !== null && { proofCount },
|
|
5349
|
+
...lastObservedAt !== null && { lastObservedAt },
|
|
5350
|
+
// C2 — algorithmic trend from evidence timestamps (no LLM). Honor
|
|
5351
|
+
// RecallOptions.now so back-dated eval harnesses get consistent labels.
|
|
5352
|
+
observationTrend: classifyObservationTrend(
|
|
5353
|
+
{
|
|
5354
|
+
createdAt,
|
|
5355
|
+
lastObservedAt,
|
|
5356
|
+
proofCount
|
|
5357
|
+
},
|
|
5358
|
+
now ?? Date.now()
|
|
5359
|
+
),
|
|
5257
5360
|
// r.similarity from searchVaultMemoriesWithSize is the fused score
|
|
5258
5361
|
// (cosine + BM25 + RRF + recency + proof) when useFusion=true (the
|
|
5259
5362
|
// default) and pure cosine when useFusion=false. The breakdown
|
|
@@ -5262,7 +5365,7 @@ function toFactMemory(r) {
|
|
|
5262
5365
|
content: r.content,
|
|
5263
5366
|
score: r.similarity,
|
|
5264
5367
|
scoreBreakdown: { fused: r.similarity },
|
|
5265
|
-
createdAt
|
|
5368
|
+
createdAt,
|
|
5266
5369
|
updatedAt: r.updatedAt ?? /* @__PURE__ */ new Date(0)
|
|
5267
5370
|
};
|
|
5268
5371
|
}
|
|
@@ -5430,6 +5533,10 @@ export {
|
|
|
5430
5533
|
capHopsForDensity,
|
|
5431
5534
|
traverseGraphLane,
|
|
5432
5535
|
createLlmNeighborRefiner,
|
|
5536
|
+
TREND_RECENT_WINDOW_DAYS,
|
|
5537
|
+
TREND_STALE_WINDOW_DAYS,
|
|
5538
|
+
classifyObservationTrend,
|
|
5539
|
+
summarizeObservationTrends,
|
|
5433
5540
|
recall,
|
|
5434
5541
|
preEmbedVaultMemories,
|
|
5435
5542
|
eagerEmbedContent,
|
package/dist/expo/index.cjs
CHANGED
|
@@ -4442,11 +4442,20 @@ async function getModel() {
|
|
|
4442
4442
|
function sigmoid(x) {
|
|
4443
4443
|
return 1 / (1 + Math.exp(-x));
|
|
4444
4444
|
}
|
|
4445
|
+
function formatRerankDoc(content, dateMs) {
|
|
4446
|
+
if (dateMs === null || dateMs === void 0 || !Number.isFinite(dateMs)) return content;
|
|
4447
|
+
const d = new Date(dateMs);
|
|
4448
|
+
if (!Number.isFinite(d.getTime())) return content;
|
|
4449
|
+
const yyyy = d.getFullYear();
|
|
4450
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
4451
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
4452
|
+
return `[Date: ${yyyy}-${mm}-${dd}] ${content}`;
|
|
4453
|
+
}
|
|
4445
4454
|
async function rerankPairs(query, items) {
|
|
4446
4455
|
if (items.length === 0 || !query) return [];
|
|
4447
4456
|
const { tokenizer, model } = await getModel();
|
|
4448
4457
|
const queries = items.map(() => query);
|
|
4449
|
-
const docs = items.map((i) => i.content);
|
|
4458
|
+
const docs = items.map((i) => formatRerankDoc(i.content, i.dateMs));
|
|
4450
4459
|
const tokenize2 = tokenizer;
|
|
4451
4460
|
const inputs = tokenize2(queries, { text_pair: docs, padding: true, truncation: true });
|
|
4452
4461
|
const forward = model;
|
|
@@ -5072,6 +5081,48 @@ var init_graphTraversal = __esm({
|
|
|
5072
5081
|
}
|
|
5073
5082
|
});
|
|
5074
5083
|
|
|
5084
|
+
// src/lib/memory/observationTrend.ts
|
|
5085
|
+
function toMs(value) {
|
|
5086
|
+
return value instanceof Date ? value.getTime() : value;
|
|
5087
|
+
}
|
|
5088
|
+
function classifyObservationTrend(input, now = Date.now()) {
|
|
5089
|
+
const createdMs = toMs(input.createdAt);
|
|
5090
|
+
if (!Number.isFinite(createdMs) || !Number.isFinite(now)) return "stable";
|
|
5091
|
+
const lastMsRaw = input.lastObservedAt;
|
|
5092
|
+
const lastMs = lastMsRaw !== null && lastMsRaw !== void 0 && Number.isFinite(lastMsRaw) ? Math.max(createdMs, lastMsRaw) : createdMs;
|
|
5093
|
+
const proofs = Math.max(1, input.proofCount ?? 1);
|
|
5094
|
+
const ageDays2 = Math.max(0, (now - createdMs) / DAY_MS2);
|
|
5095
|
+
const daysSinceLast = Math.max(0, (now - lastMs) / DAY_MS2);
|
|
5096
|
+
if (daysSinceLast >= TREND_STALE_WINDOW_DAYS) return "stale";
|
|
5097
|
+
if (daysSinceLast >= TREND_RECENT_WINDOW_DAYS) return "weakening";
|
|
5098
|
+
if (ageDays2 <= TREND_RECENT_WINDOW_DAYS && proofs <= 2) return "new";
|
|
5099
|
+
if (proofs >= 3) return "strengthening";
|
|
5100
|
+
if (proofs >= 2 && ageDays2 > TREND_RECENT_WINDOW_DAYS) return "strengthening";
|
|
5101
|
+
return "stable";
|
|
5102
|
+
}
|
|
5103
|
+
function summarizeObservationTrends(inputs, now = Date.now()) {
|
|
5104
|
+
const counts = {
|
|
5105
|
+
new: 0,
|
|
5106
|
+
strengthening: 0,
|
|
5107
|
+
stable: 0,
|
|
5108
|
+
weakening: 0,
|
|
5109
|
+
stale: 0
|
|
5110
|
+
};
|
|
5111
|
+
for (const input of inputs) {
|
|
5112
|
+
counts[classifyObservationTrend(input, now)]++;
|
|
5113
|
+
}
|
|
5114
|
+
return counts;
|
|
5115
|
+
}
|
|
5116
|
+
var DAY_MS2, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS;
|
|
5117
|
+
var init_observationTrend = __esm({
|
|
5118
|
+
"src/lib/memory/observationTrend.ts"() {
|
|
5119
|
+
"use strict";
|
|
5120
|
+
DAY_MS2 = 1e3 * 60 * 60 * 24;
|
|
5121
|
+
TREND_RECENT_WINDOW_DAYS = 30;
|
|
5122
|
+
TREND_STALE_WINDOW_DAYS = 90;
|
|
5123
|
+
}
|
|
5124
|
+
});
|
|
5125
|
+
|
|
5075
5126
|
// src/lib/memory/queryTemporal.ts
|
|
5076
5127
|
function startOfDay(ts) {
|
|
5077
5128
|
const d = new Date(ts);
|
|
@@ -5471,7 +5522,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
5471
5522
|
const fuseStart = nowMs();
|
|
5472
5523
|
if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
|
|
5473
5524
|
const memories2 = [
|
|
5474
|
-
...factResults.map(toFactMemory),
|
|
5525
|
+
...factResults.map((r) => toFactMemory(r, options.now)),
|
|
5475
5526
|
...chunkResults.map(toChunkMemory)
|
|
5476
5527
|
];
|
|
5477
5528
|
memories2.sort((a, b) => b.score - a.score);
|
|
@@ -5492,7 +5543,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
5492
5543
|
const fused = rrfFuse([factRanking, chunkRanking], options.rrfK);
|
|
5493
5544
|
const byId = /* @__PURE__ */ new Map();
|
|
5494
5545
|
for (const r of factResults) {
|
|
5495
|
-
const m = toFactMemory(r);
|
|
5546
|
+
const m = toFactMemory(r, options.now);
|
|
5496
5547
|
m.score = fused.get(`fact:${r.uniqueId}`) ?? 0;
|
|
5497
5548
|
if (!m.scoreBreakdown) m.scoreBreakdown = {};
|
|
5498
5549
|
m.scoreBreakdown.fused = r.similarity;
|
|
@@ -5541,7 +5592,10 @@ async function recall(query, ctx, options = {}) {
|
|
|
5541
5592
|
...vaultSize !== void 0 && { vaultSize }
|
|
5542
5593
|
};
|
|
5543
5594
|
}
|
|
5544
|
-
function toFactMemory(r) {
|
|
5595
|
+
function toFactMemory(r, now) {
|
|
5596
|
+
const createdAt = r.createdAt ?? /* @__PURE__ */ new Date(0);
|
|
5597
|
+
const proofCount = r.proofCount ?? void 0;
|
|
5598
|
+
const lastObservedAt = r.lastObservedAt ?? null;
|
|
5545
5599
|
return {
|
|
5546
5600
|
id: r.uniqueId,
|
|
5547
5601
|
kind: "fact",
|
|
@@ -5557,6 +5611,18 @@ function toFactMemory(r) {
|
|
|
5557
5611
|
// (and UI reading them) carry the fact's type. Undefined when untyped.
|
|
5558
5612
|
...r.factType !== void 0 && { factType: r.factType },
|
|
5559
5613
|
...r.sourceChunkIds !== void 0 && r.sourceChunkIds !== null && { sourceChunkIds: r.sourceChunkIds },
|
|
5614
|
+
...proofCount !== void 0 && proofCount !== null && { proofCount },
|
|
5615
|
+
...lastObservedAt !== null && { lastObservedAt },
|
|
5616
|
+
// C2 — algorithmic trend from evidence timestamps (no LLM). Honor
|
|
5617
|
+
// RecallOptions.now so back-dated eval harnesses get consistent labels.
|
|
5618
|
+
observationTrend: classifyObservationTrend(
|
|
5619
|
+
{
|
|
5620
|
+
createdAt,
|
|
5621
|
+
lastObservedAt,
|
|
5622
|
+
proofCount
|
|
5623
|
+
},
|
|
5624
|
+
now ?? Date.now()
|
|
5625
|
+
),
|
|
5560
5626
|
// r.similarity from searchVaultMemoriesWithSize is the fused score
|
|
5561
5627
|
// (cosine + BM25 + RRF + recency + proof) when useFusion=true (the
|
|
5562
5628
|
// default) and pure cosine when useFusion=false. The breakdown
|
|
@@ -5565,7 +5631,7 @@ function toFactMemory(r) {
|
|
|
5565
5631
|
content: r.content,
|
|
5566
5632
|
score: r.similarity,
|
|
5567
5633
|
scoreBreakdown: { fused: r.similarity },
|
|
5568
|
-
createdAt
|
|
5634
|
+
createdAt,
|
|
5569
5635
|
updatedAt: r.updatedAt ?? /* @__PURE__ */ new Date(0)
|
|
5570
5636
|
};
|
|
5571
5637
|
}
|
|
@@ -5648,6 +5714,7 @@ var init_recall = __esm({
|
|
|
5648
5714
|
init_embeddings();
|
|
5649
5715
|
init_searchTool();
|
|
5650
5716
|
init_graphTraversal();
|
|
5717
|
+
init_observationTrend();
|
|
5651
5718
|
init_queryEntities();
|
|
5652
5719
|
init_queryTemporal();
|
|
5653
5720
|
init_rrf();
|
|
@@ -5663,6 +5730,23 @@ var init_recall = __esm({
|
|
|
5663
5730
|
function normalizeEventTimeKind(kind) {
|
|
5664
5731
|
return kind === "point" || kind === "range" || kind === "ongoing" ? kind : null;
|
|
5665
5732
|
}
|
|
5733
|
+
function rerankDateMs(item) {
|
|
5734
|
+
if (item.eventTimeStart !== null && item.eventTimeStart !== void 0 && Number.isFinite(item.eventTimeStart) && item.eventTimeStart > 0) {
|
|
5735
|
+
return item.eventTimeStart;
|
|
5736
|
+
}
|
|
5737
|
+
if (item.lastObservedAt !== null && item.lastObservedAt !== void 0 && Number.isFinite(item.lastObservedAt) && item.lastObservedAt > 0) {
|
|
5738
|
+
return item.lastObservedAt;
|
|
5739
|
+
}
|
|
5740
|
+
const updatedMs = item.updatedAt?.getTime();
|
|
5741
|
+
if (updatedMs !== null && updatedMs !== void 0 && Number.isFinite(updatedMs) && updatedMs > 0) {
|
|
5742
|
+
return updatedMs;
|
|
5743
|
+
}
|
|
5744
|
+
const createdMs = item.createdAt?.getTime();
|
|
5745
|
+
if (createdMs !== null && createdMs !== void 0 && Number.isFinite(createdMs) && createdMs > 0) {
|
|
5746
|
+
return createdMs;
|
|
5747
|
+
}
|
|
5748
|
+
return void 0;
|
|
5749
|
+
}
|
|
5666
5750
|
function supersessionDelta(olderScore, newerScore, boostFactor = SUPERSESSION_BOOST_FACTOR) {
|
|
5667
5751
|
const gap = olderScore - newerScore;
|
|
5668
5752
|
return gap * boostFactor;
|
|
@@ -5865,6 +5949,7 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
5865
5949
|
}
|
|
5866
5950
|
let combined;
|
|
5867
5951
|
let tailSlice = [];
|
|
5952
|
+
const itemById = new Map(items.map((i) => [i.id, i]));
|
|
5868
5953
|
if (options?.rerank) {
|
|
5869
5954
|
const rerankTopN = options.rerankTopN ?? 30;
|
|
5870
5955
|
const ceWeight = options.ceWeight ?? 0.1;
|
|
@@ -5872,7 +5957,12 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
5872
5957
|
try {
|
|
5873
5958
|
const reranked = await rerankPairs(
|
|
5874
5959
|
query,
|
|
5875
|
-
headSlice.map((r) => ({
|
|
5960
|
+
headSlice.map((r) => ({
|
|
5961
|
+
id: r.uniqueId,
|
|
5962
|
+
content: r.content,
|
|
5963
|
+
// C4: date-prefix the CE doc so temporal alignment influences rank.
|
|
5964
|
+
dateMs: rerankDateMs(itemById.get(r.uniqueId) ?? r)
|
|
5965
|
+
}))
|
|
5876
5966
|
);
|
|
5877
5967
|
tailSlice = v2Ranked.slice(rerankTopN);
|
|
5878
5968
|
const v2ScoreById = new Map(headSlice.map((r) => [r.uniqueId, r.similarity]));
|
|
@@ -5907,11 +5997,11 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
5907
5997
|
const fused = rrfFuse([headIds, headIds, ...sideLanesAsync], options?.rrfK);
|
|
5908
5998
|
const fusedHead = combined.map((r) => ({ ...r, similarity: fused.get(r.uniqueId) ?? r.similarity })).sort((a, b) => b.similarity - a.similarity);
|
|
5909
5999
|
const seen = new Set(combined.map((r) => r.uniqueId));
|
|
5910
|
-
const
|
|
6000
|
+
const itemById2 = new Map(items.map((i) => [i.id, i]));
|
|
5911
6001
|
for (const lane of sideLanesAsync) {
|
|
5912
6002
|
for (const id of lane) {
|
|
5913
6003
|
if (seen.has(id)) continue;
|
|
5914
|
-
const it =
|
|
6004
|
+
const it = itemById2.get(id);
|
|
5915
6005
|
if (!it) continue;
|
|
5916
6006
|
fusedHead.push({
|
|
5917
6007
|
uniqueId: id,
|
|
@@ -5930,11 +6020,11 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
5930
6020
|
if (options?.mmr) {
|
|
5931
6021
|
const lambda = options.mmrLambda ?? 0.7;
|
|
5932
6022
|
const mmrTopN = options.mmrTopN ?? 20;
|
|
5933
|
-
const
|
|
6023
|
+
const itemById2 = new Map(items.map((i) => [i.id, i]));
|
|
5934
6024
|
const mmrCandidates = combined.slice(0, mmrTopN).map((r) => ({
|
|
5935
6025
|
id: r.uniqueId,
|
|
5936
6026
|
score: r.similarity,
|
|
5937
|
-
embedding:
|
|
6027
|
+
embedding: itemById2.get(r.uniqueId)?.embedding ?? [],
|
|
5938
6028
|
content: r.content
|
|
5939
6029
|
}));
|
|
5940
6030
|
const picked = applyMMR(mmrCandidates, limit, lambda);
|
|
@@ -6056,7 +6146,12 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
6056
6146
|
try {
|
|
6057
6147
|
const reranked = await rerankPairs(
|
|
6058
6148
|
originalQuery,
|
|
6059
|
-
headSlice.map((r) => ({
|
|
6149
|
+
headSlice.map((r) => ({
|
|
6150
|
+
id: r.uniqueId,
|
|
6151
|
+
content: r.content,
|
|
6152
|
+
// C4: date-prefix the CE doc so temporal alignment influences rank.
|
|
6153
|
+
dateMs: rerankDateMs(itemById.get(r.uniqueId) ?? r)
|
|
6154
|
+
}))
|
|
6060
6155
|
);
|
|
6061
6156
|
const ceById = new Map(reranked.map((r) => [r.id, r.score]));
|
|
6062
6157
|
const head = headSlice.map((r) => ({
|
|
@@ -6243,6 +6338,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
6243
6338
|
createdAt: m.createdAt,
|
|
6244
6339
|
updatedAt: m.updatedAt,
|
|
6245
6340
|
proofCount: m.proofCount,
|
|
6341
|
+
lastObservedAt: m.lastObservedAt,
|
|
6246
6342
|
eventTimeStart: m.eventTimeStart,
|
|
6247
6343
|
sourceChunkIds: m.sourceChunkIds,
|
|
6248
6344
|
eventTimeEnd: m.eventTimeEnd,
|
|
@@ -6259,13 +6355,27 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
6259
6355
|
);
|
|
6260
6356
|
}
|
|
6261
6357
|
}
|
|
6262
|
-
const
|
|
6263
|
-
memories.map((m) => [
|
|
6358
|
+
const metaById = new Map(
|
|
6359
|
+
memories.map((m) => [
|
|
6360
|
+
m.uniqueId,
|
|
6361
|
+
{
|
|
6362
|
+
createdAt: m.createdAt,
|
|
6363
|
+
updatedAt: m.updatedAt,
|
|
6364
|
+
proofCount: m.proofCount,
|
|
6365
|
+
lastObservedAt: m.lastObservedAt
|
|
6366
|
+
}
|
|
6367
|
+
])
|
|
6264
6368
|
);
|
|
6265
6369
|
const stampTimestamps = (out) => {
|
|
6266
6370
|
const results2 = out.results.map((r) => {
|
|
6267
|
-
const
|
|
6268
|
-
return
|
|
6371
|
+
const meta = metaById.get(r.uniqueId);
|
|
6372
|
+
return meta ? {
|
|
6373
|
+
...r,
|
|
6374
|
+
createdAt: meta.createdAt,
|
|
6375
|
+
updatedAt: meta.updatedAt,
|
|
6376
|
+
proofCount: meta.proofCount,
|
|
6377
|
+
lastObservedAt: meta.lastObservedAt
|
|
6378
|
+
} : r;
|
|
6269
6379
|
});
|
|
6270
6380
|
return {
|
|
6271
6381
|
results: results2,
|
|
@@ -6707,6 +6817,8 @@ __export(index_exports, {
|
|
|
6707
6817
|
StreamExpiredError: () => StreamExpiredError,
|
|
6708
6818
|
TOPICS_EXTRACTION_VERSION: () => TOPICS_EXTRACTION_VERSION,
|
|
6709
6819
|
TOPIC_EXTRACTION_BATCH_SIZE: () => TOPIC_EXTRACTION_BATCH_SIZE,
|
|
6820
|
+
TREND_RECENT_WINDOW_DAYS: () => TREND_RECENT_WINDOW_DAYS,
|
|
6821
|
+
TREND_STALE_WINDOW_DAYS: () => TREND_STALE_WINDOW_DAYS,
|
|
6710
6822
|
VAULT_SIZE_HOP_CAP: () => VAULT_SIZE_HOP_CAP,
|
|
6711
6823
|
WalletPoller: () => WalletPoller,
|
|
6712
6824
|
addConversationMemoriesOp: () => addConversationMemoriesOp,
|
|
@@ -6722,6 +6834,7 @@ __export(index_exports, {
|
|
|
6722
6834
|
classifyCryptoPriceBatch: () => classifyCryptoPriceBatch,
|
|
6723
6835
|
classifyDecay: () => classifyDecay,
|
|
6724
6836
|
classifyInjectionCandidates: () => classifyInjectionCandidates,
|
|
6837
|
+
classifyObservationTrend: () => classifyObservationTrend,
|
|
6725
6838
|
classifyStockPrice: () => classifyStockPrice,
|
|
6726
6839
|
classifyStockPriceBatch: () => classifyStockPriceBatch,
|
|
6727
6840
|
classifyWeather: () => classifyWeather,
|
|
@@ -6821,6 +6934,7 @@ __export(index_exports, {
|
|
|
6821
6934
|
stampTopicsExtractedAtOp: () => stampTopicsExtractedAtOp,
|
|
6822
6935
|
streamCancelPath: () => streamCancelPath,
|
|
6823
6936
|
streamReplayPath: () => streamReplayPath,
|
|
6937
|
+
summarizeObservationTrends: () => summarizeObservationTrends,
|
|
6824
6938
|
supersedeVaultMemoryOp: () => supersedeVaultMemoryOp,
|
|
6825
6939
|
synthesizeProfile: () => synthesizeProfile,
|
|
6826
6940
|
traverseGraphLane: () => traverseGraphLane,
|
|
@@ -14703,12 +14817,12 @@ function createChunkVectorCache(maxSize = DEFAULT_CHUNK_CACHE_SIZE) {
|
|
|
14703
14817
|
|
|
14704
14818
|
// src/lib/memory/decay.ts
|
|
14705
14819
|
init_logger();
|
|
14706
|
-
var
|
|
14707
|
-
var SHORT_TTL_MS = 30 *
|
|
14708
|
-
var MEDIUM_TTL_MS = 180 *
|
|
14820
|
+
var DAY_MS3 = 24 * 60 * 60 * 1e3;
|
|
14821
|
+
var SHORT_TTL_MS = 30 * DAY_MS3;
|
|
14822
|
+
var MEDIUM_TTL_MS = 180 * DAY_MS3;
|
|
14709
14823
|
var NEVER_TTL_MS = Number.POSITIVE_INFINITY;
|
|
14710
|
-
var HARD_DELETE_WINDOW_MS = 30 *
|
|
14711
|
-
var PAST_EVENT_GRACE_MS = 7 *
|
|
14824
|
+
var HARD_DELETE_WINDOW_MS = 30 * DAY_MS3;
|
|
14825
|
+
var PAST_EVENT_GRACE_MS = 7 * DAY_MS3;
|
|
14712
14826
|
var DEFAULT_DECAY_POLICY = {
|
|
14713
14827
|
ttlByType: {
|
|
14714
14828
|
identity: NEVER_TTL_MS,
|
|
@@ -14968,6 +15082,7 @@ function createDecaySweeper(options) {
|
|
|
14968
15082
|
|
|
14969
15083
|
// src/lib/memory/index.ts
|
|
14970
15084
|
init_graphTraversal();
|
|
15085
|
+
init_observationTrend();
|
|
14971
15086
|
init_recall();
|
|
14972
15087
|
|
|
14973
15088
|
// src/lib/memory/recallTool.ts
|
|
@@ -15334,6 +15449,7 @@ init_logger();
|
|
|
15334
15449
|
init_constants();
|
|
15335
15450
|
init_embeddings();
|
|
15336
15451
|
init_vector();
|
|
15452
|
+
init_observationTrend();
|
|
15337
15453
|
var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
|
|
15338
15454
|
var DEFAULT_FACET_RECALL_LIMIT = 20;
|
|
15339
15455
|
var DEFAULT_FACET_MAX_TOKENS = 512;
|
|
@@ -15419,6 +15535,13 @@ async function synthesizeProfile(ctx, options = {}) {
|
|
|
15419
15535
|
includeSuperseded: true
|
|
15420
15536
|
});
|
|
15421
15537
|
const watermark = computeVaultWatermark(memories);
|
|
15538
|
+
const observationTrends = summarizeObservationTrends(
|
|
15539
|
+
memories.filter((m) => !m.isDeleted && m.supersededBy === null).map((m) => ({
|
|
15540
|
+
createdAt: m.createdAt,
|
|
15541
|
+
lastObservedAt: m.lastObservedAt,
|
|
15542
|
+
proofCount: m.proofCount
|
|
15543
|
+
}))
|
|
15544
|
+
);
|
|
15422
15545
|
const presentIds = new Set(memories.map((m) => m.uniqueId));
|
|
15423
15546
|
const hasStaleSections = previous?.sections.some((s) => s.stale);
|
|
15424
15547
|
const citesMissingFact = previous?.sections.some(
|
|
@@ -15426,10 +15549,14 @@ async function synthesizeProfile(ctx, options = {}) {
|
|
|
15426
15549
|
);
|
|
15427
15550
|
if (previous && previous.vaultWatermark === watermark && !hasStaleSections && !citesMissingFact) {
|
|
15428
15551
|
const sameOrder = previous.sections.length === facets.length && facets.every((f, i) => previous.sections[i]?.key === f.key);
|
|
15429
|
-
if (sameOrder)
|
|
15552
|
+
if (sameOrder) {
|
|
15553
|
+
if (trendsEqual(previous.observationTrends, observationTrends)) return previous;
|
|
15554
|
+
return { ...previous, observationTrends };
|
|
15555
|
+
}
|
|
15430
15556
|
return {
|
|
15431
15557
|
...previous,
|
|
15432
|
-
sections: facets.map((f) => previous.sections.find((s) => s.key === f.key))
|
|
15558
|
+
sections: facets.map((f) => previous.sections.find((s) => s.key === f.key)),
|
|
15559
|
+
observationTrends
|
|
15433
15560
|
};
|
|
15434
15561
|
}
|
|
15435
15562
|
const staleKeys = await computeStaleFacetKeys(ctx, memories, facets, previous, watermark);
|
|
@@ -15462,6 +15589,7 @@ async function synthesizeProfile(ctx, options = {}) {
|
|
|
15462
15589
|
sections,
|
|
15463
15590
|
vaultWatermark: watermark,
|
|
15464
15591
|
config,
|
|
15592
|
+
observationTrends,
|
|
15465
15593
|
generatedAt: Date.now()
|
|
15466
15594
|
};
|
|
15467
15595
|
}
|
|
@@ -15472,6 +15600,10 @@ function configMatches(a, b) {
|
|
|
15472
15600
|
function facetsSignature(facets) {
|
|
15473
15601
|
return facets.map((f) => JSON.stringify([f.key, f.label, f.query, f.guidance])).sort().join("\n");
|
|
15474
15602
|
}
|
|
15603
|
+
function trendsEqual(a, b) {
|
|
15604
|
+
if (!a) return false;
|
|
15605
|
+
return a.new === b.new && a.strengthening === b.strengthening && a.stable === b.stable && a.weakening === b.weakening && a.stale === b.stale;
|
|
15606
|
+
}
|
|
15475
15607
|
function changeTime(m) {
|
|
15476
15608
|
return Math.max(m.updatedAt.getTime(), m.supersededAt ?? 0, m.lastObservedAt ?? 0);
|
|
15477
15609
|
}
|
|
@@ -21226,6 +21358,8 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
|
|
|
21226
21358
|
StreamExpiredError,
|
|
21227
21359
|
TOPICS_EXTRACTION_VERSION,
|
|
21228
21360
|
TOPIC_EXTRACTION_BATCH_SIZE,
|
|
21361
|
+
TREND_RECENT_WINDOW_DAYS,
|
|
21362
|
+
TREND_STALE_WINDOW_DAYS,
|
|
21229
21363
|
VAULT_SIZE_HOP_CAP,
|
|
21230
21364
|
WalletPoller,
|
|
21231
21365
|
addConversationMemoriesOp,
|
|
@@ -21241,6 +21375,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
|
|
|
21241
21375
|
classifyCryptoPriceBatch,
|
|
21242
21376
|
classifyDecay,
|
|
21243
21377
|
classifyInjectionCandidates,
|
|
21378
|
+
classifyObservationTrend,
|
|
21244
21379
|
classifyStockPrice,
|
|
21245
21380
|
classifyStockPriceBatch,
|
|
21246
21381
|
classifyWeather,
|
|
@@ -21340,6 +21475,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
|
|
|
21340
21475
|
stampTopicsExtractedAtOp,
|
|
21341
21476
|
streamCancelPath,
|
|
21342
21477
|
streamReplayPath,
|
|
21478
|
+
summarizeObservationTrends,
|
|
21343
21479
|
supersedeVaultMemoryOp,
|
|
21344
21480
|
synthesizeProfile,
|
|
21345
21481
|
traverseGraphLane,
|