@anuma/sdk 6.43.0 → 6.44.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/{consolidate-7WCBP5J7.mjs → consolidate-TOITBD6W.mjs} +1 -1
- package/dist/expo/index.cjs +526 -150
- package/dist/expo/index.d.mts +88 -56
- package/dist/expo/index.d.ts +88 -56
- package/dist/expo/index.mjs +515 -140
- package/dist/index.cjs +16 -8
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +14 -8
- package/dist/memory/context.d.mts +1 -0
- package/dist/memory/context.d.ts +1 -0
- package/dist/react/{consolidate-IW7EKXHN.mjs → consolidate-ZEINV2LX.mjs} +1 -1
- package/dist/react/index.cjs +353 -85
- package/dist/react/index.d.mts +87 -50
- package/dist/react/index.d.ts +87 -50
- package/dist/react/index.mjs +342 -75
- package/dist/server/{consolidate-YEGACWLR.mjs → consolidate-WY6BHODK.mjs} +1 -1
- package/dist/server/index.cjs +289 -67
- package/dist/server/index.d.mts +83 -48
- package/dist/server/index.d.ts +83 -48
- package/dist/server/index.mjs +278 -57
- package/dist/telemetry/index.d.mts +1 -0
- package/dist/telemetry/index.d.ts +1 -0
- package/dist/tools/selection/index.cjs +14 -2
- package/dist/tools/selection/index.mjs +14 -2
- package/package.json +1 -1
- package/dist/expo/{chunk-RQ3B2IYV.mjs → chunk-AF37N5Z6.mjs} +1 -1
- package/dist/react/{chunk-CERRBFF5.mjs → chunk-TGLAOFVA.mjs} +1 -1
- package/dist/server/{chunk-4RGGAOAJ.mjs → chunk-WCG5BFI6.mjs} +1 -1
package/dist/expo/index.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
taskTypeHeader,
|
|
21
21
|
validateEndpointOverride,
|
|
22
22
|
withInternalFlowMarker
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-AF37N5Z6.mjs";
|
|
24
24
|
import {
|
|
25
25
|
BASE_URL,
|
|
26
26
|
MCP_R2_DOMAIN,
|
|
@@ -3738,7 +3738,10 @@ async function embedOne(text14, options, outer) {
|
|
|
3738
3738
|
const cached = cache.get(text14);
|
|
3739
3739
|
if (cached) return Array.from(cached);
|
|
3740
3740
|
}
|
|
3741
|
-
const headers =
|
|
3741
|
+
const headers = {
|
|
3742
|
+
...await resolveAuthHeaders(options, outer),
|
|
3743
|
+
...taskTypeHeader(options.taskType)
|
|
3744
|
+
};
|
|
3742
3745
|
const response = await withEmbeddingRetry(
|
|
3743
3746
|
() => withDeadline(
|
|
3744
3747
|
(signal) => postApiV1Embeddings({
|
|
@@ -3833,7 +3836,10 @@ async function embedMany(texts, options, outer) {
|
|
|
3833
3836
|
if (uncachedTexts.length === 0) {
|
|
3834
3837
|
return results;
|
|
3835
3838
|
}
|
|
3836
|
-
const headers =
|
|
3839
|
+
const headers = {
|
|
3840
|
+
...await resolveAuthHeaders(options, outer),
|
|
3841
|
+
...taskTypeHeader(options.taskType)
|
|
3842
|
+
};
|
|
3837
3843
|
if (outer?.aborted) throw outer.reason;
|
|
3838
3844
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
3839
3845
|
let newEmbeddings;
|
|
@@ -13541,6 +13547,50 @@ function applyMMR(candidates, k, lambda = 0.5) {
|
|
|
13541
13547
|
return selected;
|
|
13542
13548
|
}
|
|
13543
13549
|
|
|
13550
|
+
// src/lib/memory/recallTelemetry.ts
|
|
13551
|
+
function notifyMemoryCallback(callback, value) {
|
|
13552
|
+
try {
|
|
13553
|
+
callback?.(value);
|
|
13554
|
+
} catch {
|
|
13555
|
+
return;
|
|
13556
|
+
}
|
|
13557
|
+
}
|
|
13558
|
+
function factRecallDiagnostics(scores, elapsedMs, options = {}) {
|
|
13559
|
+
return {
|
|
13560
|
+
usedBudget: "low",
|
|
13561
|
+
reranked: false,
|
|
13562
|
+
candidateCount: options.candidateCount ?? scores.length,
|
|
13563
|
+
...options.vaultSize !== void 0 && { vaultSize: options.vaultSize },
|
|
13564
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
13565
|
+
...options.vaultRowsDecrypted !== void 0 && {
|
|
13566
|
+
vaultRowsDecrypted: options.vaultRowsDecrypted
|
|
13567
|
+
},
|
|
13568
|
+
...options.vaultRowsEmbedded !== void 0 && {
|
|
13569
|
+
vaultRowsEmbedded: options.vaultRowsEmbedded
|
|
13570
|
+
},
|
|
13571
|
+
factCount: scores.length,
|
|
13572
|
+
chunkCount: 0,
|
|
13573
|
+
admittedCount: scores.length,
|
|
13574
|
+
topScore: scores.length ? Math.max(...scores) : -1,
|
|
13575
|
+
lowestAdmittedScore: scores.length ? Math.min(...scores) : -1,
|
|
13576
|
+
minScoreApplied: options.minScore ?? -1,
|
|
13577
|
+
truncated: options.truncated ?? false,
|
|
13578
|
+
graphLaneCount: 0,
|
|
13579
|
+
temporalLaneCount: 0,
|
|
13580
|
+
emptyReason: scores.length ? "" : options.vaultSize === 0 ? "vault-empty" : "no-candidates",
|
|
13581
|
+
timings: {
|
|
13582
|
+
total: elapsedMs,
|
|
13583
|
+
prep: 0,
|
|
13584
|
+
factLane: elapsedMs,
|
|
13585
|
+
rerank: 0,
|
|
13586
|
+
queryEmbed: options.queryEmbedMs ?? 0,
|
|
13587
|
+
chunkLane: 0,
|
|
13588
|
+
fuse: 0
|
|
13589
|
+
},
|
|
13590
|
+
degraded: options.embeddingsUnavailable ? ["embeddings-unavailable"] : []
|
|
13591
|
+
};
|
|
13592
|
+
}
|
|
13593
|
+
|
|
13544
13594
|
// src/lib/memory/recency.ts
|
|
13545
13595
|
var DAY_MS2 = 1e3 * 60 * 60 * 24;
|
|
13546
13596
|
var DEFAULT_PER_YEAR_DECAY = 0.2;
|
|
@@ -14230,6 +14280,7 @@ function rankVaultMemories(_query, queryEmbedding, items, options) {
|
|
|
14230
14280
|
}
|
|
14231
14281
|
filtered.sort((a, b) => b.similarity - a.similarity);
|
|
14232
14282
|
}
|
|
14283
|
+
notifyMemoryCallback(options?.onCandidateCount, filtered.length);
|
|
14233
14284
|
const itemById = new Map(items.map((i) => [i.id, i]));
|
|
14234
14285
|
return filtered.slice(0, limit).map((r) => resultFromItem(itemById.get(r.uniqueId), r.similarity));
|
|
14235
14286
|
}
|
|
@@ -15212,6 +15263,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
15212
15263
|
const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
15213
15264
|
limit,
|
|
15214
15265
|
minSimilarity,
|
|
15266
|
+
onCandidateCount: searchOptions?.onCandidateCount,
|
|
15215
15267
|
...searchOptions?.supersessionBoost !== void 0 && {
|
|
15216
15268
|
supersessionBoost: searchOptions.supersessionBoost
|
|
15217
15269
|
},
|
|
@@ -15312,16 +15364,20 @@ var DEFAULT_SCOPE = "private";
|
|
|
15312
15364
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
15313
15365
|
var DEFAULT_CONSOLIDATE_TOP_K = 20;
|
|
15314
15366
|
async function retain(content, ctx, options = {}) {
|
|
15367
|
+
const embeddingOptions = {
|
|
15368
|
+
...ctx.embeddingOptions,
|
|
15369
|
+
taskType: "memory_retain_embed"
|
|
15370
|
+
};
|
|
15315
15371
|
return retainWithPersistence(
|
|
15316
15372
|
content,
|
|
15317
15373
|
{
|
|
15318
|
-
embeddingOptions
|
|
15374
|
+
embeddingOptions,
|
|
15319
15375
|
vaultCache: ctx.vaultCache,
|
|
15320
15376
|
persistence: {
|
|
15321
15377
|
prepare: (query, searchOptions) => prepareVaultCandidates(
|
|
15322
15378
|
query,
|
|
15323
15379
|
ctx.vaultCtx,
|
|
15324
|
-
|
|
15380
|
+
embeddingOptions,
|
|
15325
15381
|
ctx.vaultCache,
|
|
15326
15382
|
searchOptions
|
|
15327
15383
|
),
|
|
@@ -15605,7 +15661,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
15605
15661
|
content: m.content,
|
|
15606
15662
|
similarity: m.similarity
|
|
15607
15663
|
}));
|
|
15608
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
15664
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-TOITBD6W.mjs");
|
|
15609
15665
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
15610
15666
|
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
15611
15667
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -16469,7 +16525,17 @@ function parseVerdict(parsed) {
|
|
|
16469
16525
|
}
|
|
16470
16526
|
|
|
16471
16527
|
// src/lib/memory/decayWorker.ts
|
|
16472
|
-
|
|
16528
|
+
function emptyResult() {
|
|
16529
|
+
return {
|
|
16530
|
+
archived: 0,
|
|
16531
|
+
deleted: 0,
|
|
16532
|
+
scanned: 0,
|
|
16533
|
+
ruleDriven: { archived: 0, deleted: 0 },
|
|
16534
|
+
classifierDriven: { archived: 0, deleted: 0 },
|
|
16535
|
+
classifierCalls: 0,
|
|
16536
|
+
classifierCapHits: 0
|
|
16537
|
+
};
|
|
16538
|
+
}
|
|
16473
16539
|
var DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP = 20;
|
|
16474
16540
|
function resolveNow(now) {
|
|
16475
16541
|
if (typeof now === "function") return now();
|
|
@@ -16508,42 +16574,45 @@ function createDecaySweeper(options) {
|
|
|
16508
16574
|
let disposed = false;
|
|
16509
16575
|
async function verdictFor(input, now, sweep) {
|
|
16510
16576
|
const ruleVerdict = classifyDecay(input, now, policy);
|
|
16511
|
-
|
|
16512
|
-
if (
|
|
16577
|
+
const rule = { verdict: ruleVerdict, source: "ruleDriven" };
|
|
16578
|
+
if (ruleVerdict !== "keep") return rule;
|
|
16579
|
+
if (!classifier || !isBorderline(input)) return rule;
|
|
16513
16580
|
if (input.id) {
|
|
16514
16581
|
const cached = classifierCache.get(input.id);
|
|
16515
|
-
if (cached && cached.activityAt === lastActivityAt(input))
|
|
16582
|
+
if (cached && cached.activityAt === lastActivityAt(input))
|
|
16583
|
+
return { verdict: cached.verdict, source: "classifierDriven" };
|
|
16516
16584
|
}
|
|
16517
16585
|
if (sweep.classifierCalls >= maxClassifierCalls) {
|
|
16586
|
+
sweep.classifierCapHits++;
|
|
16518
16587
|
if (!sweep.ceilingLogged) {
|
|
16519
16588
|
sweep.ceilingLogged = true;
|
|
16520
16589
|
getLogger().warn(
|
|
16521
16590
|
`[memory/decay] classifier per-sweep ceiling (${maxClassifierCalls}) reached; remaining borderline rows use the rule verdict this sweep`
|
|
16522
16591
|
);
|
|
16523
16592
|
}
|
|
16524
|
-
return
|
|
16593
|
+
return rule;
|
|
16525
16594
|
}
|
|
16526
16595
|
sweep.classifierCalls++;
|
|
16527
16596
|
try {
|
|
16528
16597
|
const verdict = await classifier.classify(input, ruleVerdict, now);
|
|
16529
16598
|
if (input.id) classifierCache.set(input.id, { activityAt: lastActivityAt(input), verdict });
|
|
16530
|
-
return verdict;
|
|
16599
|
+
return { verdict, source: "classifierDriven" };
|
|
16531
16600
|
} catch (err) {
|
|
16532
16601
|
getLogger().warn(
|
|
16533
16602
|
`[memory/decay] classifier failed; falling back to rule verdict: ${err instanceof Error ? err.message : String(err)}`
|
|
16534
16603
|
);
|
|
16535
|
-
return
|
|
16604
|
+
return rule;
|
|
16536
16605
|
}
|
|
16537
16606
|
}
|
|
16538
16607
|
async function runSweep() {
|
|
16539
|
-
if (disposed) return
|
|
16608
|
+
if (disposed) return emptyResult();
|
|
16540
16609
|
const now = resolveNow(options.now);
|
|
16541
16610
|
let candidates;
|
|
16542
16611
|
try {
|
|
16543
16612
|
candidates = await getDecayCandidatesRawOp(vaultCtx);
|
|
16544
16613
|
} catch (err) {
|
|
16545
16614
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
16546
|
-
return
|
|
16615
|
+
return emptyResult();
|
|
16547
16616
|
}
|
|
16548
16617
|
if (classifierCache.size > 0) {
|
|
16549
16618
|
const liveIds = new Set(candidates.map((c) => c.uniqueId));
|
|
@@ -16551,33 +16620,40 @@ function createDecaySweeper(options) {
|
|
|
16551
16620
|
if (!liveIds.has(id)) classifierCache.delete(id);
|
|
16552
16621
|
}
|
|
16553
16622
|
}
|
|
16554
|
-
const sweep = { classifierCalls: 0, ceilingLogged: false };
|
|
16623
|
+
const sweep = { classifierCalls: 0, classifierCapHits: 0, ceilingLogged: false };
|
|
16555
16624
|
const toArchive = [];
|
|
16556
16625
|
const toDelete = [];
|
|
16557
16626
|
for (const c of candidates) {
|
|
16558
|
-
const verdict = await verdictFor(toDecayInput(c), now, sweep);
|
|
16559
|
-
if (verdict === "archive") toArchive.push(c);
|
|
16560
|
-
else if (verdict === "delete") toDelete.push(c);
|
|
16561
|
-
}
|
|
16562
|
-
|
|
16563
|
-
|
|
16627
|
+
const { verdict, source } = await verdictFor(toDecayInput(c), now, sweep);
|
|
16628
|
+
if (verdict === "archive") toArchive.push({ candidate: c, source });
|
|
16629
|
+
else if (verdict === "delete") toDelete.push({ candidate: c, source });
|
|
16630
|
+
}
|
|
16631
|
+
const result = emptyResult();
|
|
16632
|
+
result.scanned = candidates.length;
|
|
16633
|
+
result.classifierCalls = sweep.classifierCalls;
|
|
16634
|
+
result.classifierCapHits = sweep.classifierCapHits;
|
|
16564
16635
|
try {
|
|
16565
|
-
for (const c of toArchive) {
|
|
16636
|
+
for (const { candidate: c, source } of toArchive) {
|
|
16566
16637
|
const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
|
|
16567
16638
|
now,
|
|
16568
16639
|
expectedUpdatedAt: c.updatedAt,
|
|
16569
16640
|
expectedLastObservedAt: c.lastObservedAt ?? null
|
|
16570
16641
|
});
|
|
16571
|
-
if (ok)
|
|
16642
|
+
if (ok) {
|
|
16643
|
+
result.archived++;
|
|
16644
|
+
result[source].archived++;
|
|
16645
|
+
}
|
|
16572
16646
|
}
|
|
16573
|
-
for (const c of toDelete) {
|
|
16647
|
+
for (const { candidate: c, source } of toDelete) {
|
|
16574
16648
|
const ok = await hardDeleteDecayedOp(vaultCtx, c.uniqueId, { hardDeleteWindowMs, now });
|
|
16575
|
-
if (ok)
|
|
16649
|
+
if (ok) {
|
|
16650
|
+
result.deleted++;
|
|
16651
|
+
result[source].deleted++;
|
|
16652
|
+
}
|
|
16576
16653
|
}
|
|
16577
16654
|
} catch (err) {
|
|
16578
16655
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
16579
16656
|
}
|
|
16580
|
-
const result = { archived, deleted, scanned: candidates.length };
|
|
16581
16657
|
onSwept?.(result);
|
|
16582
16658
|
return result;
|
|
16583
16659
|
}
|
|
@@ -17175,6 +17251,10 @@ async function recall(query, ctx, options = {}) {
|
|
|
17175
17251
|
const flags = flagsForBudget(usedBudget);
|
|
17176
17252
|
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
17177
17253
|
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
17254
|
+
const embeddingOptions = {
|
|
17255
|
+
...ctx.embeddingOptions,
|
|
17256
|
+
taskType: "memory_recall_embed"
|
|
17257
|
+
};
|
|
17178
17258
|
const t0 = nowMs2();
|
|
17179
17259
|
let prepMs = 0;
|
|
17180
17260
|
let factLaneMs = 0;
|
|
@@ -17270,7 +17350,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
17270
17350
|
let sharedEmbedMs = 0;
|
|
17271
17351
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
17272
17352
|
needsChunkEmbedding ? generateEmbedding(query, {
|
|
17273
|
-
...
|
|
17353
|
+
...embeddingOptions,
|
|
17274
17354
|
totalTimeoutMs: queryEmbedTotalTimeoutMs
|
|
17275
17355
|
}).finally(() => {
|
|
17276
17356
|
sharedEmbedMs = nowMs2() - prepStart;
|
|
@@ -17328,7 +17408,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
17328
17408
|
} = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
|
|
17329
17409
|
searchQuery,
|
|
17330
17410
|
ctx.vaultCtx,
|
|
17331
|
-
|
|
17411
|
+
embeddingOptions,
|
|
17332
17412
|
ctx.vaultCache,
|
|
17333
17413
|
searchOptions
|
|
17334
17414
|
)))(query, {
|
|
@@ -17694,7 +17774,7 @@ function isDumpQuery(query) {
|
|
|
17694
17774
|
async function listRecentFacts(ctx, limit, toolOptions) {
|
|
17695
17775
|
const store = toolOptions?.memoryStore;
|
|
17696
17776
|
const vaultCtx = ctx.vaultCtx;
|
|
17697
|
-
if (!vaultCtx && !store) return [];
|
|
17777
|
+
if (!vaultCtx && !store) return { memories: [], truncated: false };
|
|
17698
17778
|
const read = (ids) => store ? store.list({ memoryIds: ids }) : getVaultMemoriesByIdsOp(vaultCtx, ids);
|
|
17699
17779
|
const filters = {
|
|
17700
17780
|
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
@@ -17705,34 +17785,47 @@ async function listRecentFacts(ctx, limit, toolOptions) {
|
|
|
17705
17785
|
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId }
|
|
17706
17786
|
});
|
|
17707
17787
|
const readable = [];
|
|
17788
|
+
const readLimit = limit + 1;
|
|
17789
|
+
let batchLimit = limit;
|
|
17708
17790
|
let start = 0;
|
|
17709
|
-
|
|
17791
|
+
let projected = 0;
|
|
17792
|
+
let exhausted = false;
|
|
17793
|
+
for (let size = readLimit; readable.length < readLimit; size *= 2) {
|
|
17710
17794
|
const ordered = await project(size);
|
|
17711
|
-
|
|
17712
|
-
|
|
17795
|
+
projected = ordered.length;
|
|
17796
|
+
exhausted = !store || ordered.length < size;
|
|
17797
|
+
for (let i = start; i < ordered.length && readable.length < readLimit; ) {
|
|
17798
|
+
const batch = ordered.slice(i, i + batchLimit).map((p) => p.uniqueId);
|
|
17713
17799
|
const byId = new Map((await read(batch)).map((m) => [m.uniqueId, m]));
|
|
17800
|
+
const previousCount = readable.length;
|
|
17714
17801
|
for (const id of batch) {
|
|
17715
17802
|
const m = byId.get(id);
|
|
17716
17803
|
if (m && !isEncrypted(m.content)) readable.push(m);
|
|
17717
|
-
if (readable.length >=
|
|
17804
|
+
if (readable.length >= readLimit) break;
|
|
17718
17805
|
}
|
|
17806
|
+
batchLimit = readable.length > previousCount ? Math.min(limit, readLimit - readable.length) : limit;
|
|
17807
|
+
i += batch.length;
|
|
17719
17808
|
}
|
|
17720
|
-
if (
|
|
17809
|
+
if (exhausted) break;
|
|
17721
17810
|
start = ordered.length;
|
|
17722
17811
|
}
|
|
17723
|
-
return
|
|
17724
|
-
|
|
17725
|
-
|
|
17726
|
-
|
|
17727
|
-
|
|
17728
|
-
|
|
17729
|
-
|
|
17730
|
-
|
|
17731
|
-
|
|
17732
|
-
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
|
|
17812
|
+
return {
|
|
17813
|
+
memories: readable.slice(0, limit).map((m) => ({
|
|
17814
|
+
id: m.uniqueId,
|
|
17815
|
+
kind: "fact",
|
|
17816
|
+
content: m.content,
|
|
17817
|
+
score: 0,
|
|
17818
|
+
folderId: m.folderId,
|
|
17819
|
+
eventTimeStart: m.eventTimeStart,
|
|
17820
|
+
eventTimeEnd: m.eventTimeEnd,
|
|
17821
|
+
eventTimeKind: m.eventTimeKind,
|
|
17822
|
+
factType: m.factType,
|
|
17823
|
+
createdAt: m.createdAt,
|
|
17824
|
+
updatedAt: m.updatedAt
|
|
17825
|
+
})),
|
|
17826
|
+
...exhausted && { vaultSize: projected },
|
|
17827
|
+
truncated: readable.length > limit
|
|
17828
|
+
};
|
|
17736
17829
|
}
|
|
17737
17830
|
function createRecallTool(ctx, toolOptions, callbacks) {
|
|
17738
17831
|
if (toolOptions?.memoryStore && toolOptions.folderId !== void 0)
|
|
@@ -17771,7 +17864,11 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17771
17864
|
},
|
|
17772
17865
|
executor: async (args) => {
|
|
17773
17866
|
if (typeof args.query !== "string" || args.query.length === 0) {
|
|
17774
|
-
|
|
17867
|
+
const error = new Error(
|
|
17868
|
+
"recall_memory: `query` is required and must be a non-empty string."
|
|
17869
|
+
);
|
|
17870
|
+
notifyMemoryCallback(callbacks?.onError, error);
|
|
17871
|
+
throw error;
|
|
17775
17872
|
}
|
|
17776
17873
|
const query = args.query;
|
|
17777
17874
|
const now = Date.now();
|
|
@@ -17799,10 +17896,17 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17799
17896
|
RECALL_MAX_MEMORIES_PER_CONVERSATION - conversationMemories
|
|
17800
17897
|
);
|
|
17801
17898
|
const effectiveLimit = Math.min(requestLimit, remainingTurnBudget, remainingConvBudget);
|
|
17899
|
+
const truncatedByBudget = effectiveLimit < requestLimit;
|
|
17900
|
+
if (truncatedByBudget) {
|
|
17901
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
17902
|
+
requestedLimit: requestLimit,
|
|
17903
|
+
effectiveLimit,
|
|
17904
|
+
truncatedByBudget
|
|
17905
|
+
});
|
|
17906
|
+
}
|
|
17802
17907
|
if (effectiveLimit <= 0) {
|
|
17803
17908
|
return VOLUME_LIMIT_NOTICE;
|
|
17804
17909
|
}
|
|
17805
|
-
const truncatedByBudget = effectiveLimit < requestLimit;
|
|
17806
17910
|
turnMemories += effectiveLimit;
|
|
17807
17911
|
conversationMemories += effectiveLimit;
|
|
17808
17912
|
let surfaced = 0;
|
|
@@ -17811,7 +17915,27 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17811
17915
|
const wantsRecent = args.sort === "recent" && defaultTypes.includes("fact") && (ctx.vaultCtx !== void 0 || toolOptions?.memoryStore !== void 0);
|
|
17812
17916
|
let result;
|
|
17813
17917
|
if (wantsRecent) {
|
|
17814
|
-
|
|
17918
|
+
const start = Date.now();
|
|
17919
|
+
const recent = await listRecentFacts(ctx, effectiveLimit, toolOptions);
|
|
17920
|
+
result = recent;
|
|
17921
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, {
|
|
17922
|
+
...factRecallDiagnostics(
|
|
17923
|
+
result.memories.map((m) => m.score),
|
|
17924
|
+
Date.now() - start,
|
|
17925
|
+
{
|
|
17926
|
+
truncated: recent.truncated,
|
|
17927
|
+
...recent.vaultSize !== void 0 && { vaultSize: recent.vaultSize }
|
|
17928
|
+
}
|
|
17929
|
+
),
|
|
17930
|
+
truncatedByBudget
|
|
17931
|
+
});
|
|
17932
|
+
if (recent.truncated && !truncatedByBudget) {
|
|
17933
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
17934
|
+
requestedLimit: requestLimit,
|
|
17935
|
+
effectiveLimit,
|
|
17936
|
+
truncatedByBudget
|
|
17937
|
+
});
|
|
17938
|
+
}
|
|
17815
17939
|
} else {
|
|
17816
17940
|
let subQueries;
|
|
17817
17941
|
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
@@ -17823,6 +17947,14 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17823
17947
|
const recallOpts = {
|
|
17824
17948
|
onDiagnostics: (d) => {
|
|
17825
17949
|
recallDegraded = d.degraded;
|
|
17950
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, { ...d, truncatedByBudget });
|
|
17951
|
+
if (d.truncated && !truncatedByBudget) {
|
|
17952
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
17953
|
+
requestedLimit: requestLimit,
|
|
17954
|
+
effectiveLimit,
|
|
17955
|
+
truncatedByBudget
|
|
17956
|
+
});
|
|
17957
|
+
}
|
|
17826
17958
|
},
|
|
17827
17959
|
types: defaultTypes,
|
|
17828
17960
|
limit: effectiveLimit,
|
|
@@ -17866,6 +17998,7 @@ ${TRUNCATION_NOTICE}` : formatted;
|
|
|
17866
17998
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
17867
17999
|
const wrapped = new Error(`recall_memory: search failed \u2014 ${message}`);
|
|
17868
18000
|
wrapped.cause = error;
|
|
18001
|
+
notifyMemoryCallback(callbacks?.onError, wrapped);
|
|
17869
18002
|
throw wrapped;
|
|
17870
18003
|
} finally {
|
|
17871
18004
|
const unused = effectiveLimit - surfaced;
|
|
@@ -18099,6 +18232,18 @@ When a memory refers to one of these, reuse the EXACT existing name (same spelli
|
|
|
18099
18232
|
` : "";
|
|
18100
18233
|
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
|
18101
18234
|
const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
|
|
18235
|
+
const start = Date.now();
|
|
18236
|
+
let attempts = 0;
|
|
18237
|
+
let failure;
|
|
18238
|
+
const reportBatch = (unansweredCount) => {
|
|
18239
|
+
notifyMemoryCallback(options.onBatch, {
|
|
18240
|
+
memoryIds: batch.map((m) => m.id),
|
|
18241
|
+
attempts,
|
|
18242
|
+
durationMs: Date.now() - start,
|
|
18243
|
+
unansweredCount,
|
|
18244
|
+
...failure && { failure }
|
|
18245
|
+
});
|
|
18246
|
+
};
|
|
18102
18247
|
const rows = [];
|
|
18103
18248
|
for (const m of batch) {
|
|
18104
18249
|
const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
|
|
@@ -18120,6 +18265,12 @@ ${listing}
|
|
|
18120
18265
|
|
|
18121
18266
|
List each memory's named entities.`,
|
|
18122
18267
|
tag: "memory/topics",
|
|
18268
|
+
onAttempt: (attempt) => {
|
|
18269
|
+
attempts = attempt.attempt;
|
|
18270
|
+
},
|
|
18271
|
+
onFailure: (value) => {
|
|
18272
|
+
failure = value;
|
|
18273
|
+
},
|
|
18123
18274
|
extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
|
|
18124
18275
|
...options.fetchFn && { fetchFn: options.fetchFn },
|
|
18125
18276
|
...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
|
|
@@ -18128,6 +18279,7 @@ List each memory's named entities.`,
|
|
|
18128
18279
|
...options.backoffMs && { backoffMs: options.backoffMs }
|
|
18129
18280
|
});
|
|
18130
18281
|
if (parsed === null) {
|
|
18282
|
+
reportBatch(batch.length);
|
|
18131
18283
|
getLogger().warn(
|
|
18132
18284
|
`[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
|
|
18133
18285
|
);
|
|
@@ -18136,6 +18288,7 @@ List each memory's named entities.`,
|
|
|
18136
18288
|
const validIds = new Set(batch.map((m) => m.id));
|
|
18137
18289
|
const byId = parseTopicResponse(parsed, validIds);
|
|
18138
18290
|
if (byId === null) {
|
|
18291
|
+
reportBatch(batch.length);
|
|
18139
18292
|
getLogger().warn(
|
|
18140
18293
|
`[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
|
|
18141
18294
|
);
|
|
@@ -18148,6 +18301,7 @@ List each memory's named entities.`,
|
|
|
18148
18301
|
}
|
|
18149
18302
|
out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
|
|
18150
18303
|
}
|
|
18304
|
+
reportBatch(batch.filter((m) => !byId.has(m.id)).length);
|
|
18151
18305
|
}
|
|
18152
18306
|
return out;
|
|
18153
18307
|
}
|
|
@@ -18186,6 +18340,7 @@ function isDegradedTopicSkip(reason) {
|
|
|
18186
18340
|
return DEGRADED_TOPIC_SKIP[reason] === true;
|
|
18187
18341
|
}
|
|
18188
18342
|
async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
18343
|
+
const start = Date.now();
|
|
18189
18344
|
const entityCtx = ctx.entityCtx;
|
|
18190
18345
|
if (!entityCtx) {
|
|
18191
18346
|
throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
|
|
@@ -18226,7 +18381,18 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
18226
18381
|
skip(id, "unreadable");
|
|
18227
18382
|
}
|
|
18228
18383
|
}
|
|
18229
|
-
const
|
|
18384
|
+
const batches = [];
|
|
18385
|
+
const llmFailures = /* @__PURE__ */ new Map();
|
|
18386
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, {
|
|
18387
|
+
...options,
|
|
18388
|
+
onBatch: (batch) => {
|
|
18389
|
+
batches.push(batch);
|
|
18390
|
+
if (batch.failure) {
|
|
18391
|
+
for (const id of batch.memoryIds) llmFailures.set(id, batch.failure);
|
|
18392
|
+
}
|
|
18393
|
+
notifyMemoryCallback(options.onBatch, batch);
|
|
18394
|
+
}
|
|
18395
|
+
});
|
|
18230
18396
|
const toStamp = [];
|
|
18231
18397
|
for (const input of inputs) {
|
|
18232
18398
|
const entities = entitiesByMemory.get(input.id);
|
|
@@ -18257,7 +18423,16 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
18257
18423
|
entitiesByMemory.delete(id);
|
|
18258
18424
|
}
|
|
18259
18425
|
}
|
|
18260
|
-
return {
|
|
18426
|
+
return {
|
|
18427
|
+
entitiesByMemory,
|
|
18428
|
+
stampedIds,
|
|
18429
|
+
skippedIds,
|
|
18430
|
+
skippedReasons,
|
|
18431
|
+
batchCount: batches.length,
|
|
18432
|
+
durationMs: Date.now() - start,
|
|
18433
|
+
batches,
|
|
18434
|
+
llmFailures
|
|
18435
|
+
};
|
|
18261
18436
|
}
|
|
18262
18437
|
|
|
18263
18438
|
// src/lib/memory/store/local.ts
|
|
@@ -18412,7 +18587,7 @@ function createLocalMemoryStore(options) {
|
|
|
18412
18587
|
search: (query, searchOptions) => searchVaultMemoriesWithSize(
|
|
18413
18588
|
query,
|
|
18414
18589
|
vaultCtx,
|
|
18415
|
-
options.embeddingOptions,
|
|
18590
|
+
{ ...options.embeddingOptions, taskType: "memory_recall_embed" },
|
|
18416
18591
|
vaultCache,
|
|
18417
18592
|
searchOptions
|
|
18418
18593
|
),
|
|
@@ -19074,6 +19249,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19074
19249
|
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
19075
19250
|
const embed = (texts) => generateEmbeddings(texts, {
|
|
19076
19251
|
...embeddingOptions,
|
|
19252
|
+
taskType: mode === "retain" ? "memory_retain_embed" : "memory_recall_embed",
|
|
19077
19253
|
totalTimeoutMs: budgetMs
|
|
19078
19254
|
});
|
|
19079
19255
|
const embedFacets = async () => {
|
|
@@ -19322,7 +19498,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19322
19498
|
const ranked = await rankPreparedVaultCandidates(
|
|
19323
19499
|
text14,
|
|
19324
19500
|
prepared,
|
|
19325
|
-
embeddingOptions,
|
|
19501
|
+
{ ...embeddingOptions, taskType: "memory_recall_embed" },
|
|
19326
19502
|
searchOptions
|
|
19327
19503
|
);
|
|
19328
19504
|
return {
|
|
@@ -19344,7 +19520,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19344
19520
|
content,
|
|
19345
19521
|
{
|
|
19346
19522
|
persistence: port,
|
|
19347
|
-
embeddingOptions,
|
|
19523
|
+
embeddingOptions: { ...embeddingOptions, taskType: "memory_retain_embed" },
|
|
19348
19524
|
vaultCache: /* @__PURE__ */ new Map(),
|
|
19349
19525
|
normalizeEmbedding: storedVector
|
|
19350
19526
|
},
|
|
@@ -19720,6 +19896,7 @@ var MAX_BATCH = 50;
|
|
|
19720
19896
|
var MAX_QUERY_IDS = 1e3;
|
|
19721
19897
|
var MAX_QUERY_TOPICS = 100;
|
|
19722
19898
|
var MAX_QUERY_FILTER = 20;
|
|
19899
|
+
var GRAPH_LANE_ROWS = 256;
|
|
19723
19900
|
var RemoteMemoryPartialCreateError = class extends Error {
|
|
19724
19901
|
constructor(created, cause) {
|
|
19725
19902
|
super(`createMany stored ${created.length} memories before a batch failed`);
|
|
@@ -19815,7 +19992,11 @@ function createRemoteMemoryStore(options) {
|
|
|
19815
19992
|
const { persistence, embeddingOptions } = options;
|
|
19816
19993
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19817
19994
|
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
19818
|
-
const pipeline = createRemoteMemoryPipeline(
|
|
19995
|
+
const pipeline = createRemoteMemoryPipeline({
|
|
19996
|
+
...options,
|
|
19997
|
+
graphRanking: options.graphRanking ?? ((query, _traverse, recallOptions) => topicGraphRanking(query, recallOptions)),
|
|
19998
|
+
temporalRanking: options.temporalRanking ?? (() => Promise.resolve([]))
|
|
19999
|
+
});
|
|
19819
20000
|
const subscribers = /* @__PURE__ */ new Set();
|
|
19820
20001
|
const seen = /* @__PURE__ */ new Map();
|
|
19821
20002
|
let timer;
|
|
@@ -19847,6 +20028,36 @@ function createRemoteMemoryStore(options) {
|
|
|
19847
20028
|
const decrypted = (options2) => persistence.query(options2);
|
|
19848
20029
|
const metadata2 = (options2) => persistence.queryMetadata(options2);
|
|
19849
20030
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
20031
|
+
const memoriesByTopics = async (names) => {
|
|
20032
|
+
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
20033
|
+
const out = /* @__PURE__ */ new Map();
|
|
20034
|
+
const pages2 = await Promise.all(
|
|
20035
|
+
chunks2([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
20036
|
+
);
|
|
20037
|
+
for (const { memory } of pages2.flat()) {
|
|
20038
|
+
const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
|
|
20039
|
+
if (matched.length) out.set(memory.memory_id, new Set(matched));
|
|
20040
|
+
}
|
|
20041
|
+
return out;
|
|
20042
|
+
};
|
|
20043
|
+
const topicGraphRanking = async (query, recallOptions = {}) => {
|
|
20044
|
+
const wanted = new Set(extractQueryEntities(query).map(normalizeEntityName).filter(Boolean));
|
|
20045
|
+
if (wanted.size === 0 || recallOptions.memoryIds?.length === 0) return [];
|
|
20046
|
+
const rows = await pages(
|
|
20047
|
+
metadata2,
|
|
20048
|
+
{
|
|
20049
|
+
topics: [...wanted].slice(0, MAX_QUERY_TOPICS),
|
|
20050
|
+
...recallOptions.scopes && { scopes: recallOptions.scopes },
|
|
20051
|
+
...recallOptions.factTypes && { fact_types: recallOptions.factTypes },
|
|
20052
|
+
...recallOptions.memoryIds && { memory_ids: recallOptions.memoryIds }
|
|
20053
|
+
},
|
|
20054
|
+
GRAPH_LANE_ROWS
|
|
20055
|
+
);
|
|
20056
|
+
return rows.map(({ memory }) => ({
|
|
20057
|
+
memoryId: memory.memory_id,
|
|
20058
|
+
matched: [...canonicalTopics(memory)].filter((name) => wanted.has(name)).length
|
|
20059
|
+
})).filter((row) => row.matched > 0).sort((a, b) => b.matched - a.matched).slice(0, NODE_BUDGET).map((row) => row.memoryId);
|
|
20060
|
+
};
|
|
19850
20061
|
const enumerateIds = async (read, ids, filters) => (await Promise.all(
|
|
19851
20062
|
chunks2([...new Set(ids)], MAX_QUERY_IDS).map(
|
|
19852
20063
|
(memory_ids) => pages(read, { ...filters, memory_ids })
|
|
@@ -20072,7 +20283,8 @@ function createRemoteMemoryStore(options) {
|
|
|
20072
20283
|
};
|
|
20073
20284
|
},
|
|
20074
20285
|
extractTopics: async (memoryIds, extractOptions) => {
|
|
20075
|
-
const
|
|
20286
|
+
const start = Date.now();
|
|
20287
|
+
const extractedAt = extractOptions.now ?? start;
|
|
20076
20288
|
const skippedIds = [];
|
|
20077
20289
|
const skippedReasons = /* @__PURE__ */ new Map();
|
|
20078
20290
|
const skip = (id, reason) => {
|
|
@@ -20090,7 +20302,18 @@ function createRemoteMemoryStore(options) {
|
|
|
20090
20302
|
else if (memory.is_deleted || memory.topics_user_managed) skip(id, "excluded");
|
|
20091
20303
|
else inputs.push({ id, content: memory.content });
|
|
20092
20304
|
}
|
|
20093
|
-
const
|
|
20305
|
+
const batches = [];
|
|
20306
|
+
const llmFailures = /* @__PURE__ */ new Map();
|
|
20307
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, {
|
|
20308
|
+
...extractOptions,
|
|
20309
|
+
onBatch: (batch) => {
|
|
20310
|
+
batches.push(batch);
|
|
20311
|
+
if (batch.failure) {
|
|
20312
|
+
for (const id of batch.memoryIds) llmFailures.set(id, batch.failure);
|
|
20313
|
+
}
|
|
20314
|
+
notifyMemoryCallback(extractOptions.onBatch, batch);
|
|
20315
|
+
}
|
|
20316
|
+
});
|
|
20094
20317
|
const answered = /* @__PURE__ */ new Map();
|
|
20095
20318
|
for (const input of inputs) {
|
|
20096
20319
|
const entities = entitiesByMemory.get(input.id);
|
|
@@ -20139,7 +20362,16 @@ function createRemoteMemoryStore(options) {
|
|
|
20139
20362
|
getLogger().warn("[memory/remote-store] Failed to write extracted topics:", error);
|
|
20140
20363
|
for (const id of answered.keys()) fail(id, "link-failed");
|
|
20141
20364
|
}
|
|
20142
|
-
return {
|
|
20365
|
+
return {
|
|
20366
|
+
entitiesByMemory,
|
|
20367
|
+
stampedIds,
|
|
20368
|
+
skippedIds,
|
|
20369
|
+
skippedReasons,
|
|
20370
|
+
batchCount: batches.length,
|
|
20371
|
+
durationMs: Date.now() - start,
|
|
20372
|
+
batches,
|
|
20373
|
+
llmFailures
|
|
20374
|
+
};
|
|
20143
20375
|
},
|
|
20144
20376
|
stampTopicsExtracted: async (memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) => {
|
|
20145
20377
|
const ids = [...new Set(memoryIds)];
|
|
@@ -20266,18 +20498,7 @@ function createRemoteMemoryStore(options) {
|
|
|
20266
20498
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
20267
20499
|
(record2) => stored(record2.memory)
|
|
20268
20500
|
),
|
|
20269
|
-
memoriesByTopics
|
|
20270
|
-
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
20271
|
-
const out = /* @__PURE__ */ new Map();
|
|
20272
|
-
const pages2 = await Promise.all(
|
|
20273
|
-
chunks2([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
20274
|
-
);
|
|
20275
|
-
for (const { memory } of pages2.flat()) {
|
|
20276
|
-
const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
|
|
20277
|
-
if (matched.length) out.set(memory.memory_id, new Set(matched));
|
|
20278
|
-
}
|
|
20279
|
-
return out;
|
|
20280
|
-
},
|
|
20501
|
+
memoriesByTopics,
|
|
20281
20502
|
topicsByMemories: async (memoryIds) => {
|
|
20282
20503
|
const out = /* @__PURE__ */ new Map();
|
|
20283
20504
|
for (const { memory } of await enumerateIds(decrypted, memoryIds, {
|
|
@@ -22150,9 +22371,13 @@ function formatVaultHits(hits) {
|
|
|
22150
22371
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
22151
22372
|
${h.content}`).join("\n\n");
|
|
22152
22373
|
}
|
|
22153
|
-
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
22374
|
+
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions, callbacks) {
|
|
22154
22375
|
const limit = searchOptions?.limit ?? 5;
|
|
22155
22376
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
22377
|
+
const recallEmbeddingOptions = {
|
|
22378
|
+
...embeddingOptions,
|
|
22379
|
+
taskType: "memory_recall_embed"
|
|
22380
|
+
};
|
|
22156
22381
|
const tuningForward = {
|
|
22157
22382
|
...searchOptions?.rerankTopN !== void 0 && { rerankTopN: searchOptions.rerankTopN },
|
|
22158
22383
|
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
@@ -22206,6 +22431,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22206
22431
|
const requestLimit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.floor(rawLimit), 1), RECALL_MAX_LIMIT) : limit;
|
|
22207
22432
|
const argFolderId = args.folder_id;
|
|
22208
22433
|
if (!query || typeof query !== "string") {
|
|
22434
|
+
notifyMemoryCallback(callbacks?.onError, new Error("A search query is required."));
|
|
22209
22435
|
return "Error: A search query is required.";
|
|
22210
22436
|
}
|
|
22211
22437
|
try {
|
|
@@ -22213,7 +22439,11 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22213
22439
|
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
22214
22440
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
22215
22441
|
if (searchOptions?.useFusion === false) {
|
|
22442
|
+
let candidateCount;
|
|
22216
22443
|
const legacyOptions = {
|
|
22444
|
+
onCandidateCount: (count2) => {
|
|
22445
|
+
candidateCount = count2;
|
|
22446
|
+
},
|
|
22217
22447
|
limit: requestLimit,
|
|
22218
22448
|
minSimilarity,
|
|
22219
22449
|
useFusion: false,
|
|
@@ -22221,13 +22451,38 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22221
22451
|
...folderId !== void 0 && { folderId },
|
|
22222
22452
|
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
22223
22453
|
};
|
|
22224
|
-
const
|
|
22454
|
+
const start = Date.now();
|
|
22455
|
+
const outcome2 = "retain" in vaultCtx ? await vaultCtx.factSource.search(query, legacyOptions) : await searchVaultMemoriesWithSize(
|
|
22225
22456
|
query,
|
|
22226
22457
|
vaultCtx,
|
|
22227
|
-
|
|
22458
|
+
recallEmbeddingOptions,
|
|
22228
22459
|
cache,
|
|
22229
22460
|
legacyOptions
|
|
22230
22461
|
);
|
|
22462
|
+
const { results: legacy, embeddingsUnavailable, vaultSize } = outcome2;
|
|
22463
|
+
const diagnostics = factRecallDiagnostics(
|
|
22464
|
+
legacy.map((m) => m.similarity),
|
|
22465
|
+
Date.now() - start,
|
|
22466
|
+
{
|
|
22467
|
+
vaultSize,
|
|
22468
|
+
minScore: minSimilarity,
|
|
22469
|
+
embeddingsUnavailable,
|
|
22470
|
+
candidateCount,
|
|
22471
|
+
truncated: candidateCount !== void 0 && candidateCount > requestLimit,
|
|
22472
|
+
decryptLast: outcome2.decryptLast,
|
|
22473
|
+
vaultRowsDecrypted: outcome2.rowsDecrypted,
|
|
22474
|
+
vaultRowsEmbedded: outcome2.rowsEmbedded,
|
|
22475
|
+
queryEmbedMs: outcome2.queryEmbedMs
|
|
22476
|
+
}
|
|
22477
|
+
);
|
|
22478
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, diagnostics);
|
|
22479
|
+
if (diagnostics.truncated) {
|
|
22480
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
22481
|
+
requestedLimit: requestLimit,
|
|
22482
|
+
effectiveLimit: requestLimit,
|
|
22483
|
+
truncatedByBudget: false
|
|
22484
|
+
});
|
|
22485
|
+
}
|
|
22231
22486
|
if (legacy.length === 0) {
|
|
22232
22487
|
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
22233
22488
|
}
|
|
@@ -22249,6 +22504,14 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22249
22504
|
{
|
|
22250
22505
|
onDiagnostics: (d) => {
|
|
22251
22506
|
recallDegraded = d.degraded;
|
|
22507
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, d);
|
|
22508
|
+
if (d.truncated) {
|
|
22509
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
22510
|
+
requestedLimit: requestLimit,
|
|
22511
|
+
effectiveLimit: requestLimit,
|
|
22512
|
+
truncatedByBudget: false
|
|
22513
|
+
});
|
|
22514
|
+
}
|
|
22252
22515
|
},
|
|
22253
22516
|
types: ["fact"],
|
|
22254
22517
|
limit: requestLimit,
|
|
@@ -22281,6 +22544,10 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22281
22544
|
|
|
22282
22545
|
${formatted}`;
|
|
22283
22546
|
} catch (error) {
|
|
22547
|
+
notifyMemoryCallback(
|
|
22548
|
+
callbacks?.onError,
|
|
22549
|
+
error instanceof Error ? error : new Error(String(error))
|
|
22550
|
+
);
|
|
22284
22551
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
22285
22552
|
return `Error searching vault: ${message}`;
|
|
22286
22553
|
}
|
|
@@ -23746,6 +24013,15 @@ function useChat(options) {
|
|
|
23746
24013
|
detachControllerRef.current = null;
|
|
23747
24014
|
pendingResumeRef.current = null;
|
|
23748
24015
|
}, [resumable, fireCancel]);
|
|
24016
|
+
const cancel = useCallback3(
|
|
24017
|
+
(handle) => {
|
|
24018
|
+
if (resumable) fireCancel(handle);
|
|
24019
|
+
if (pendingResumeRef.current?.inferenceId === handle.inferenceId) {
|
|
24020
|
+
pendingResumeRef.current = null;
|
|
24021
|
+
}
|
|
24022
|
+
},
|
|
24023
|
+
[resumable, fireCancel]
|
|
24024
|
+
);
|
|
23749
24025
|
const detach = useCallback3(() => {
|
|
23750
24026
|
if (detachControllerRef.current) {
|
|
23751
24027
|
detachControllerRef.current.abort();
|
|
@@ -24004,6 +24280,7 @@ function useChat(options) {
|
|
|
24004
24280
|
isLoading,
|
|
24005
24281
|
sendMessage,
|
|
24006
24282
|
stop,
|
|
24283
|
+
cancel,
|
|
24007
24284
|
detach,
|
|
24008
24285
|
resumeStream: resumeStream2
|
|
24009
24286
|
};
|
|
@@ -25403,6 +25680,7 @@ function useChatStorage(options) {
|
|
|
25403
25680
|
isLoading,
|
|
25404
25681
|
sendMessage: baseSendMessage,
|
|
25405
25682
|
stop: baseStop,
|
|
25683
|
+
cancel: baseCancel,
|
|
25406
25684
|
detach,
|
|
25407
25685
|
resumeStream: baseResumeStream
|
|
25408
25686
|
} = useChat({
|
|
@@ -25426,6 +25704,9 @@ function useChatStorage(options) {
|
|
|
25426
25704
|
});
|
|
25427
25705
|
const pendingResumeRef = useRef4(null);
|
|
25428
25706
|
const isResumingRef = useRef4(false);
|
|
25707
|
+
const activeResumeRef = useRef4(null);
|
|
25708
|
+
const retirementRef = useRef4(null);
|
|
25709
|
+
const retirementStopRequestedRef = useRef4(false);
|
|
25429
25710
|
const createConversation = useCallback4(
|
|
25430
25711
|
async (opts) => {
|
|
25431
25712
|
const { result, queued } = await writeOrQueue(
|
|
@@ -25625,6 +25906,143 @@ function useChatStorage(options) {
|
|
|
25625
25906
|
activeToolSetsRef.current = activeToolSets;
|
|
25626
25907
|
const getTokenRef = useRef4(getToken);
|
|
25627
25908
|
getTokenRef.current = getToken;
|
|
25909
|
+
const finalizeResumedRow = useCallback4(
|
|
25910
|
+
async (ctx, data, wasStopped, responseDuration, viaQueue = false) => {
|
|
25911
|
+
const { content, thinking } = extractAssistantText(data);
|
|
25912
|
+
let parentMessageId = ctx.userMessageUniqueId;
|
|
25913
|
+
let knownIds = ctx.knownToolCallEventIds;
|
|
25914
|
+
if (ctx.convId && (!knownIds || !parentMessageId)) {
|
|
25915
|
+
let storedMessages = null;
|
|
25916
|
+
try {
|
|
25917
|
+
storedMessages = await getMessages(ctx.convId);
|
|
25918
|
+
} catch {
|
|
25919
|
+
}
|
|
25920
|
+
if (storedMessages) {
|
|
25921
|
+
if (!knownIds) {
|
|
25922
|
+
knownIds = /* @__PURE__ */ new Set();
|
|
25923
|
+
for (const msg of storedMessages) {
|
|
25924
|
+
if (msg.uniqueId === ctx.assistantUniqueId) continue;
|
|
25925
|
+
if (msg.toolCallEvents) {
|
|
25926
|
+
for (const evt of msg.toolCallEvents) {
|
|
25927
|
+
if (evt.id) knownIds.add(evt.id);
|
|
25928
|
+
}
|
|
25929
|
+
}
|
|
25930
|
+
}
|
|
25931
|
+
}
|
|
25932
|
+
if (!parentMessageId) {
|
|
25933
|
+
for (let i = storedMessages.length - 1; i >= 0; i--) {
|
|
25934
|
+
if (storedMessages[i].uniqueId !== ctx.assistantUniqueId) {
|
|
25935
|
+
parentMessageId = storedMessages[i].uniqueId;
|
|
25936
|
+
break;
|
|
25937
|
+
}
|
|
25938
|
+
}
|
|
25939
|
+
}
|
|
25940
|
+
}
|
|
25941
|
+
}
|
|
25942
|
+
const allToolCallEvents = getToolCallEvents(data);
|
|
25943
|
+
const currentTurnToolCallEvents = knownIds ? allToolCallEvents?.filter(
|
|
25944
|
+
(evt) => evt.id !== void 0 && evt.id !== null && !knownIds.has(evt.id)
|
|
25945
|
+
) : allToolCallEvents;
|
|
25946
|
+
const baseSources = ctx.sources ?? [];
|
|
25947
|
+
const seenSourceUrls = new Set(
|
|
25948
|
+
baseSources.map((s) => s.url).filter((url) => !!url)
|
|
25949
|
+
);
|
|
25950
|
+
const toolEventSources = extractSourcesFromToolCallEvents(currentTurnToolCallEvents);
|
|
25951
|
+
const sources = [
|
|
25952
|
+
...baseSources,
|
|
25953
|
+
...toolEventSources.filter((s) => !s.url || !seenSourceUrls.has(s.url))
|
|
25954
|
+
].filter((source) => !source.url?.includes(MCP_R2_DOMAIN));
|
|
25955
|
+
const rowOpts = {
|
|
25956
|
+
conversationId: ctx.convId,
|
|
25957
|
+
role: "assistant",
|
|
25958
|
+
content,
|
|
25959
|
+
model: data.model || ctx.model || "",
|
|
25960
|
+
imageModel: ctx.imageModel || getImageModel(data),
|
|
25961
|
+
usage: convertUsageToStored(data),
|
|
25962
|
+
responseDuration,
|
|
25963
|
+
sources,
|
|
25964
|
+
thoughtProcess: finalizeThoughtProcess(ctx.thoughtProcess),
|
|
25965
|
+
thinking,
|
|
25966
|
+
wasStopped,
|
|
25967
|
+
parentMessageId,
|
|
25968
|
+
toolCallEvents: currentTurnToolCallEvents && currentTurnToolCallEvents.length > 0 ? currentTurnToolCallEvents : void 0,
|
|
25969
|
+
uniqueId: ctx.assistantUniqueId
|
|
25970
|
+
};
|
|
25971
|
+
if (!viaQueue) return upsertMessageOp(storageCtx, rowOpts);
|
|
25972
|
+
const { result } = await writeOrQueue(
|
|
25973
|
+
"createMessage",
|
|
25974
|
+
rowOpts,
|
|
25975
|
+
() => upsertMessageOp(storageCtx, rowOpts),
|
|
25976
|
+
() => makeSyntheticStoredMessage(rowOpts),
|
|
25977
|
+
ctx.userMessageQueueId ? [ctx.userMessageQueueId] : []
|
|
25978
|
+
);
|
|
25979
|
+
return result;
|
|
25980
|
+
},
|
|
25981
|
+
[storageCtx, getMessages, writeOrQueue]
|
|
25982
|
+
);
|
|
25983
|
+
const retirePendingTurn = useCallback4(async () => {
|
|
25984
|
+
const visible = activeResumeRef.current;
|
|
25985
|
+
if (visible && !visible.headless) {
|
|
25986
|
+
baseStop();
|
|
25987
|
+
await visible.settled;
|
|
25988
|
+
}
|
|
25989
|
+
if (retirementRef.current) return retirementRef.current;
|
|
25990
|
+
const active = activeResumeRef.current;
|
|
25991
|
+
if (active && !active.headless) return "Resume already in progress";
|
|
25992
|
+
const pending = pendingResumeRef.current;
|
|
25993
|
+
if (!pending) return null;
|
|
25994
|
+
if (!pending.userMessageUniqueId) {
|
|
25995
|
+
if (active?.context === pending) return null;
|
|
25996
|
+
if (!pending.partialData) {
|
|
25997
|
+
pendingResumeRef.current = null;
|
|
25998
|
+
return null;
|
|
25999
|
+
}
|
|
26000
|
+
}
|
|
26001
|
+
if (active?.context === pending) return "Resume already in progress";
|
|
26002
|
+
pendingResumeRef.current = null;
|
|
26003
|
+
retirementStopRequestedRef.current = false;
|
|
26004
|
+
const retirement = Promise.resolve().then(async () => {
|
|
26005
|
+
try {
|
|
26006
|
+
const data = pending.partialData;
|
|
26007
|
+
if (data && pending.assistantUniqueId) {
|
|
26008
|
+
const { content, thinking } = extractAssistantText(data);
|
|
26009
|
+
if (content || thinking || (getToolCallEvents(data)?.length ?? 0) > 0) {
|
|
26010
|
+
if (walletAddress && signMessage && !hasEncryptionKey(walletAddress)) {
|
|
26011
|
+
try {
|
|
26012
|
+
await requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner);
|
|
26013
|
+
} catch {
|
|
26014
|
+
}
|
|
26015
|
+
}
|
|
26016
|
+
await finalizeResumedRow(
|
|
26017
|
+
pending,
|
|
26018
|
+
data,
|
|
26019
|
+
true,
|
|
26020
|
+
(Date.now() - pending.startTime) / 1e3,
|
|
26021
|
+
true
|
|
26022
|
+
);
|
|
26023
|
+
}
|
|
26024
|
+
}
|
|
26025
|
+
if (pending.handle) baseCancel(pending.handle);
|
|
26026
|
+
return null;
|
|
26027
|
+
} catch (err) {
|
|
26028
|
+
pendingResumeRef.current = pending;
|
|
26029
|
+
if (retirementStopRequestedRef.current && pending.handle) {
|
|
26030
|
+
baseCancel(pending.handle);
|
|
26031
|
+
pendingResumeRef.current = { ...pending, handle: null };
|
|
26032
|
+
}
|
|
26033
|
+
return err instanceof Error ? err.message : "Failed to store detached message";
|
|
26034
|
+
}
|
|
26035
|
+
});
|
|
26036
|
+
retirementRef.current = retirement;
|
|
26037
|
+
try {
|
|
26038
|
+
return await retirement;
|
|
26039
|
+
} finally {
|
|
26040
|
+
if (retirementRef.current === retirement) {
|
|
26041
|
+
retirementRef.current = null;
|
|
26042
|
+
retirementStopRequestedRef.current = false;
|
|
26043
|
+
}
|
|
26044
|
+
}
|
|
26045
|
+
}, [baseCancel, baseStop, finalizeResumedRow, walletAddress, signMessage, embeddedWalletSigner]);
|
|
25628
26046
|
const sendMessage = useCallback4(
|
|
25629
26047
|
async (args) => {
|
|
25630
26048
|
const {
|
|
@@ -25676,7 +26094,11 @@ function useChatStorage(options) {
|
|
|
25676
26094
|
maskForCall: (text14) => redactor ? redactor.maskText(text14) : text14
|
|
25677
26095
|
};
|
|
25678
26096
|
};
|
|
25679
|
-
|
|
26097
|
+
const retirementError = await retirePendingTurn();
|
|
26098
|
+
if (retirementError) {
|
|
26099
|
+
if (!skipStorage) return { data: null, error: retirementError };
|
|
26100
|
+
getLogger().warn("[useChatStorage] detached partial not saved:", retirementError);
|
|
26101
|
+
}
|
|
25680
26102
|
const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${uuidv77()}` : void 0);
|
|
25681
26103
|
const embedToolText = (text14, mask, masked, token) => {
|
|
25682
26104
|
const opts = {
|
|
@@ -26200,6 +26622,7 @@ function useChatStorage(options) {
|
|
|
26200
26622
|
handle: detachedResult.resume ?? null,
|
|
26201
26623
|
convId,
|
|
26202
26624
|
userMessageUniqueId: storedUserMessage.uniqueId,
|
|
26625
|
+
userMessageQueueId: userMsgQueueId,
|
|
26203
26626
|
assistantUniqueId: rowId,
|
|
26204
26627
|
model,
|
|
26205
26628
|
imageModel,
|
|
@@ -26426,6 +26849,7 @@ function useChatStorage(options) {
|
|
|
26426
26849
|
getMessages,
|
|
26427
26850
|
storageCtx,
|
|
26428
26851
|
baseSendMessage,
|
|
26852
|
+
retirePendingTurn,
|
|
26429
26853
|
embedMessageAsync,
|
|
26430
26854
|
minContentLength,
|
|
26431
26855
|
walletAddress,
|
|
@@ -26440,72 +26864,9 @@ function useChatStorage(options) {
|
|
|
26440
26864
|
onPiiRedacted
|
|
26441
26865
|
]
|
|
26442
26866
|
);
|
|
26443
|
-
const finalizeResumedRow = useCallback4(
|
|
26444
|
-
async (ctx, data, wasStopped, responseDuration) => {
|
|
26445
|
-
const { content, thinking } = extractAssistantText(data);
|
|
26446
|
-
let parentMessageId = ctx.userMessageUniqueId;
|
|
26447
|
-
let knownIds = ctx.knownToolCallEventIds;
|
|
26448
|
-
if (ctx.convId && (!knownIds || !parentMessageId)) {
|
|
26449
|
-
let storedMessages = null;
|
|
26450
|
-
try {
|
|
26451
|
-
storedMessages = await getMessages(ctx.convId);
|
|
26452
|
-
} catch {
|
|
26453
|
-
}
|
|
26454
|
-
if (storedMessages) {
|
|
26455
|
-
if (!knownIds) {
|
|
26456
|
-
knownIds = /* @__PURE__ */ new Set();
|
|
26457
|
-
for (const msg of storedMessages) {
|
|
26458
|
-
if (msg.toolCallEvents) {
|
|
26459
|
-
for (const evt of msg.toolCallEvents) {
|
|
26460
|
-
if (evt.id) knownIds.add(evt.id);
|
|
26461
|
-
}
|
|
26462
|
-
}
|
|
26463
|
-
}
|
|
26464
|
-
}
|
|
26465
|
-
if (!parentMessageId) {
|
|
26466
|
-
for (let i = storedMessages.length - 1; i >= 0; i--) {
|
|
26467
|
-
if (storedMessages[i].uniqueId !== ctx.assistantUniqueId) {
|
|
26468
|
-
parentMessageId = storedMessages[i].uniqueId;
|
|
26469
|
-
break;
|
|
26470
|
-
}
|
|
26471
|
-
}
|
|
26472
|
-
}
|
|
26473
|
-
}
|
|
26474
|
-
}
|
|
26475
|
-
const allToolCallEvents = getToolCallEvents(data);
|
|
26476
|
-
const currentTurnToolCallEvents = knownIds ? allToolCallEvents?.filter(
|
|
26477
|
-
(evt) => evt.id !== void 0 && evt.id !== null && !knownIds.has(evt.id)
|
|
26478
|
-
) : allToolCallEvents;
|
|
26479
|
-
const baseSources = ctx.sources ?? [];
|
|
26480
|
-
const seenSourceUrls = new Set(
|
|
26481
|
-
baseSources.map((s) => s.url).filter((url) => !!url)
|
|
26482
|
-
);
|
|
26483
|
-
const toolEventSources = extractSourcesFromToolCallEvents(currentTurnToolCallEvents);
|
|
26484
|
-
const sources = [
|
|
26485
|
-
...baseSources,
|
|
26486
|
-
...toolEventSources.filter((s) => !s.url || !seenSourceUrls.has(s.url))
|
|
26487
|
-
].filter((source) => !source.url?.includes(MCP_R2_DOMAIN));
|
|
26488
|
-
return upsertMessageOp(storageCtx, {
|
|
26489
|
-
conversationId: ctx.convId,
|
|
26490
|
-
role: "assistant",
|
|
26491
|
-
content,
|
|
26492
|
-
model: data.model || ctx.model || "",
|
|
26493
|
-
imageModel: ctx.imageModel || getImageModel(data),
|
|
26494
|
-
usage: convertUsageToStored(data),
|
|
26495
|
-
responseDuration,
|
|
26496
|
-
sources,
|
|
26497
|
-
thoughtProcess: finalizeThoughtProcess(ctx.thoughtProcess),
|
|
26498
|
-
thinking,
|
|
26499
|
-
wasStopped,
|
|
26500
|
-
parentMessageId,
|
|
26501
|
-
uniqueId: ctx.assistantUniqueId
|
|
26502
|
-
});
|
|
26503
|
-
},
|
|
26504
|
-
[storageCtx, getMessages]
|
|
26505
|
-
);
|
|
26506
26867
|
const resumeStream2 = useCallback4(
|
|
26507
26868
|
async (handleOverride, opts) => {
|
|
26508
|
-
if (isResumingRef.current) {
|
|
26869
|
+
if (isResumingRef.current || retirementRef.current) {
|
|
26509
26870
|
return { data: null, error: "Resume already in progress", assistantMessage: null };
|
|
26510
26871
|
}
|
|
26511
26872
|
const pending = pendingResumeRef.current;
|
|
@@ -26534,6 +26895,7 @@ function useChatStorage(options) {
|
|
|
26534
26895
|
if (pendingResumeRef.current === rctx) pendingResumeRef.current = null;
|
|
26535
26896
|
};
|
|
26536
26897
|
const safeFinalize = async (data, wasStopped, responseDuration) => {
|
|
26898
|
+
rctx.partialData = data;
|
|
26537
26899
|
try {
|
|
26538
26900
|
return { message: await finalizeResumedRow(rctx, data, wasStopped, responseDuration) };
|
|
26539
26901
|
} catch (writeErr) {
|
|
@@ -26543,6 +26905,13 @@ function useChatStorage(options) {
|
|
|
26543
26905
|
}
|
|
26544
26906
|
};
|
|
26545
26907
|
isResumingRef.current = true;
|
|
26908
|
+
let markSettled = () => {
|
|
26909
|
+
};
|
|
26910
|
+
const settled = new Promise((resolve) => {
|
|
26911
|
+
markSettled = resolve;
|
|
26912
|
+
});
|
|
26913
|
+
const activeResume = { context: rctx, headless: opts?.headless === true, settled };
|
|
26914
|
+
activeResumeRef.current = activeResume;
|
|
26546
26915
|
try {
|
|
26547
26916
|
const result = await baseResumeStream(handle, { headless: opts?.headless });
|
|
26548
26917
|
const responseDuration = (Date.now() - rctx.startTime) / 1e3;
|
|
@@ -26619,11 +26988,17 @@ function useChatStorage(options) {
|
|
|
26619
26988
|
throw err;
|
|
26620
26989
|
} finally {
|
|
26621
26990
|
isResumingRef.current = false;
|
|
26991
|
+
if (activeResumeRef.current === activeResume) activeResumeRef.current = null;
|
|
26992
|
+
markSettled();
|
|
26622
26993
|
}
|
|
26623
26994
|
},
|
|
26624
26995
|
[baseResumeStream, currentConversationId, finalizeResumedRow, embedMessageAsync]
|
|
26625
26996
|
);
|
|
26626
26997
|
const stop = useCallback4(() => {
|
|
26998
|
+
if (retirementRef.current) {
|
|
26999
|
+
retirementStopRequestedRef.current = true;
|
|
27000
|
+
return;
|
|
27001
|
+
}
|
|
26627
27002
|
const pending = pendingResumeRef.current;
|
|
26628
27003
|
if (pending && pending.assistantUniqueId && !isResumingRef.current) {
|
|
26629
27004
|
const finalize = pending;
|