@anuma/sdk 6.43.0 → 6.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/{consolidate-7WCBP5J7.mjs → consolidate-TOITBD6W.mjs} +1 -1
- package/dist/expo/index.cjs +489 -137
- package/dist/expo/index.d.mts +84 -54
- package/dist/expo/index.d.ts +84 -54
- package/dist/expo/index.mjs +478 -127
- 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 +316 -72
- package/dist/react/index.d.mts +83 -48
- package/dist/react/index.d.ts +83 -48
- package/dist/react/index.mjs +305 -62
- 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
|
},
|
|
@@ -20072,7 +20248,8 @@ function createRemoteMemoryStore(options) {
|
|
|
20072
20248
|
};
|
|
20073
20249
|
},
|
|
20074
20250
|
extractTopics: async (memoryIds, extractOptions) => {
|
|
20075
|
-
const
|
|
20251
|
+
const start = Date.now();
|
|
20252
|
+
const extractedAt = extractOptions.now ?? start;
|
|
20076
20253
|
const skippedIds = [];
|
|
20077
20254
|
const skippedReasons = /* @__PURE__ */ new Map();
|
|
20078
20255
|
const skip = (id, reason) => {
|
|
@@ -20090,7 +20267,18 @@ function createRemoteMemoryStore(options) {
|
|
|
20090
20267
|
else if (memory.is_deleted || memory.topics_user_managed) skip(id, "excluded");
|
|
20091
20268
|
else inputs.push({ id, content: memory.content });
|
|
20092
20269
|
}
|
|
20093
|
-
const
|
|
20270
|
+
const batches = [];
|
|
20271
|
+
const llmFailures = /* @__PURE__ */ new Map();
|
|
20272
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, {
|
|
20273
|
+
...extractOptions,
|
|
20274
|
+
onBatch: (batch) => {
|
|
20275
|
+
batches.push(batch);
|
|
20276
|
+
if (batch.failure) {
|
|
20277
|
+
for (const id of batch.memoryIds) llmFailures.set(id, batch.failure);
|
|
20278
|
+
}
|
|
20279
|
+
notifyMemoryCallback(extractOptions.onBatch, batch);
|
|
20280
|
+
}
|
|
20281
|
+
});
|
|
20094
20282
|
const answered = /* @__PURE__ */ new Map();
|
|
20095
20283
|
for (const input of inputs) {
|
|
20096
20284
|
const entities = entitiesByMemory.get(input.id);
|
|
@@ -20139,7 +20327,16 @@ function createRemoteMemoryStore(options) {
|
|
|
20139
20327
|
getLogger().warn("[memory/remote-store] Failed to write extracted topics:", error);
|
|
20140
20328
|
for (const id of answered.keys()) fail(id, "link-failed");
|
|
20141
20329
|
}
|
|
20142
|
-
return {
|
|
20330
|
+
return {
|
|
20331
|
+
entitiesByMemory,
|
|
20332
|
+
stampedIds,
|
|
20333
|
+
skippedIds,
|
|
20334
|
+
skippedReasons,
|
|
20335
|
+
batchCount: batches.length,
|
|
20336
|
+
durationMs: Date.now() - start,
|
|
20337
|
+
batches,
|
|
20338
|
+
llmFailures
|
|
20339
|
+
};
|
|
20143
20340
|
},
|
|
20144
20341
|
stampTopicsExtracted: async (memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) => {
|
|
20145
20342
|
const ids = [...new Set(memoryIds)];
|
|
@@ -22150,9 +22347,13 @@ function formatVaultHits(hits) {
|
|
|
22150
22347
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
22151
22348
|
${h.content}`).join("\n\n");
|
|
22152
22349
|
}
|
|
22153
|
-
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
22350
|
+
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions, callbacks) {
|
|
22154
22351
|
const limit = searchOptions?.limit ?? 5;
|
|
22155
22352
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
22353
|
+
const recallEmbeddingOptions = {
|
|
22354
|
+
...embeddingOptions,
|
|
22355
|
+
taskType: "memory_recall_embed"
|
|
22356
|
+
};
|
|
22156
22357
|
const tuningForward = {
|
|
22157
22358
|
...searchOptions?.rerankTopN !== void 0 && { rerankTopN: searchOptions.rerankTopN },
|
|
22158
22359
|
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
@@ -22206,6 +22407,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22206
22407
|
const requestLimit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.floor(rawLimit), 1), RECALL_MAX_LIMIT) : limit;
|
|
22207
22408
|
const argFolderId = args.folder_id;
|
|
22208
22409
|
if (!query || typeof query !== "string") {
|
|
22410
|
+
notifyMemoryCallback(callbacks?.onError, new Error("A search query is required."));
|
|
22209
22411
|
return "Error: A search query is required.";
|
|
22210
22412
|
}
|
|
22211
22413
|
try {
|
|
@@ -22213,7 +22415,11 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22213
22415
|
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
22214
22416
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
22215
22417
|
if (searchOptions?.useFusion === false) {
|
|
22418
|
+
let candidateCount;
|
|
22216
22419
|
const legacyOptions = {
|
|
22420
|
+
onCandidateCount: (count2) => {
|
|
22421
|
+
candidateCount = count2;
|
|
22422
|
+
},
|
|
22217
22423
|
limit: requestLimit,
|
|
22218
22424
|
minSimilarity,
|
|
22219
22425
|
useFusion: false,
|
|
@@ -22221,13 +22427,38 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22221
22427
|
...folderId !== void 0 && { folderId },
|
|
22222
22428
|
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
22223
22429
|
};
|
|
22224
|
-
const
|
|
22430
|
+
const start = Date.now();
|
|
22431
|
+
const outcome2 = "retain" in vaultCtx ? await vaultCtx.factSource.search(query, legacyOptions) : await searchVaultMemoriesWithSize(
|
|
22225
22432
|
query,
|
|
22226
22433
|
vaultCtx,
|
|
22227
|
-
|
|
22434
|
+
recallEmbeddingOptions,
|
|
22228
22435
|
cache,
|
|
22229
22436
|
legacyOptions
|
|
22230
22437
|
);
|
|
22438
|
+
const { results: legacy, embeddingsUnavailable, vaultSize } = outcome2;
|
|
22439
|
+
const diagnostics = factRecallDiagnostics(
|
|
22440
|
+
legacy.map((m) => m.similarity),
|
|
22441
|
+
Date.now() - start,
|
|
22442
|
+
{
|
|
22443
|
+
vaultSize,
|
|
22444
|
+
minScore: minSimilarity,
|
|
22445
|
+
embeddingsUnavailable,
|
|
22446
|
+
candidateCount,
|
|
22447
|
+
truncated: candidateCount !== void 0 && candidateCount > requestLimit,
|
|
22448
|
+
decryptLast: outcome2.decryptLast,
|
|
22449
|
+
vaultRowsDecrypted: outcome2.rowsDecrypted,
|
|
22450
|
+
vaultRowsEmbedded: outcome2.rowsEmbedded,
|
|
22451
|
+
queryEmbedMs: outcome2.queryEmbedMs
|
|
22452
|
+
}
|
|
22453
|
+
);
|
|
22454
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, diagnostics);
|
|
22455
|
+
if (diagnostics.truncated) {
|
|
22456
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
22457
|
+
requestedLimit: requestLimit,
|
|
22458
|
+
effectiveLimit: requestLimit,
|
|
22459
|
+
truncatedByBudget: false
|
|
22460
|
+
});
|
|
22461
|
+
}
|
|
22231
22462
|
if (legacy.length === 0) {
|
|
22232
22463
|
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
22233
22464
|
}
|
|
@@ -22249,6 +22480,14 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22249
22480
|
{
|
|
22250
22481
|
onDiagnostics: (d) => {
|
|
22251
22482
|
recallDegraded = d.degraded;
|
|
22483
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, d);
|
|
22484
|
+
if (d.truncated) {
|
|
22485
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
22486
|
+
requestedLimit: requestLimit,
|
|
22487
|
+
effectiveLimit: requestLimit,
|
|
22488
|
+
truncatedByBudget: false
|
|
22489
|
+
});
|
|
22490
|
+
}
|
|
22252
22491
|
},
|
|
22253
22492
|
types: ["fact"],
|
|
22254
22493
|
limit: requestLimit,
|
|
@@ -22281,6 +22520,10 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
22281
22520
|
|
|
22282
22521
|
${formatted}`;
|
|
22283
22522
|
} catch (error) {
|
|
22523
|
+
notifyMemoryCallback(
|
|
22524
|
+
callbacks?.onError,
|
|
22525
|
+
error instanceof Error ? error : new Error(String(error))
|
|
22526
|
+
);
|
|
22284
22527
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
22285
22528
|
return `Error searching vault: ${message}`;
|
|
22286
22529
|
}
|
|
@@ -23746,6 +23989,15 @@ function useChat(options) {
|
|
|
23746
23989
|
detachControllerRef.current = null;
|
|
23747
23990
|
pendingResumeRef.current = null;
|
|
23748
23991
|
}, [resumable, fireCancel]);
|
|
23992
|
+
const cancel = useCallback3(
|
|
23993
|
+
(handle) => {
|
|
23994
|
+
if (resumable) fireCancel(handle);
|
|
23995
|
+
if (pendingResumeRef.current?.inferenceId === handle.inferenceId) {
|
|
23996
|
+
pendingResumeRef.current = null;
|
|
23997
|
+
}
|
|
23998
|
+
},
|
|
23999
|
+
[resumable, fireCancel]
|
|
24000
|
+
);
|
|
23749
24001
|
const detach = useCallback3(() => {
|
|
23750
24002
|
if (detachControllerRef.current) {
|
|
23751
24003
|
detachControllerRef.current.abort();
|
|
@@ -24004,6 +24256,7 @@ function useChat(options) {
|
|
|
24004
24256
|
isLoading,
|
|
24005
24257
|
sendMessage,
|
|
24006
24258
|
stop,
|
|
24259
|
+
cancel,
|
|
24007
24260
|
detach,
|
|
24008
24261
|
resumeStream: resumeStream2
|
|
24009
24262
|
};
|
|
@@ -25403,6 +25656,7 @@ function useChatStorage(options) {
|
|
|
25403
25656
|
isLoading,
|
|
25404
25657
|
sendMessage: baseSendMessage,
|
|
25405
25658
|
stop: baseStop,
|
|
25659
|
+
cancel: baseCancel,
|
|
25406
25660
|
detach,
|
|
25407
25661
|
resumeStream: baseResumeStream
|
|
25408
25662
|
} = useChat({
|
|
@@ -25426,6 +25680,9 @@ function useChatStorage(options) {
|
|
|
25426
25680
|
});
|
|
25427
25681
|
const pendingResumeRef = useRef4(null);
|
|
25428
25682
|
const isResumingRef = useRef4(false);
|
|
25683
|
+
const activeResumeRef = useRef4(null);
|
|
25684
|
+
const retirementRef = useRef4(null);
|
|
25685
|
+
const retirementStopRequestedRef = useRef4(false);
|
|
25429
25686
|
const createConversation = useCallback4(
|
|
25430
25687
|
async (opts) => {
|
|
25431
25688
|
const { result, queued } = await writeOrQueue(
|
|
@@ -25625,6 +25882,143 @@ function useChatStorage(options) {
|
|
|
25625
25882
|
activeToolSetsRef.current = activeToolSets;
|
|
25626
25883
|
const getTokenRef = useRef4(getToken);
|
|
25627
25884
|
getTokenRef.current = getToken;
|
|
25885
|
+
const finalizeResumedRow = useCallback4(
|
|
25886
|
+
async (ctx, data, wasStopped, responseDuration, viaQueue = false) => {
|
|
25887
|
+
const { content, thinking } = extractAssistantText(data);
|
|
25888
|
+
let parentMessageId = ctx.userMessageUniqueId;
|
|
25889
|
+
let knownIds = ctx.knownToolCallEventIds;
|
|
25890
|
+
if (ctx.convId && (!knownIds || !parentMessageId)) {
|
|
25891
|
+
let storedMessages = null;
|
|
25892
|
+
try {
|
|
25893
|
+
storedMessages = await getMessages(ctx.convId);
|
|
25894
|
+
} catch {
|
|
25895
|
+
}
|
|
25896
|
+
if (storedMessages) {
|
|
25897
|
+
if (!knownIds) {
|
|
25898
|
+
knownIds = /* @__PURE__ */ new Set();
|
|
25899
|
+
for (const msg of storedMessages) {
|
|
25900
|
+
if (msg.uniqueId === ctx.assistantUniqueId) continue;
|
|
25901
|
+
if (msg.toolCallEvents) {
|
|
25902
|
+
for (const evt of msg.toolCallEvents) {
|
|
25903
|
+
if (evt.id) knownIds.add(evt.id);
|
|
25904
|
+
}
|
|
25905
|
+
}
|
|
25906
|
+
}
|
|
25907
|
+
}
|
|
25908
|
+
if (!parentMessageId) {
|
|
25909
|
+
for (let i = storedMessages.length - 1; i >= 0; i--) {
|
|
25910
|
+
if (storedMessages[i].uniqueId !== ctx.assistantUniqueId) {
|
|
25911
|
+
parentMessageId = storedMessages[i].uniqueId;
|
|
25912
|
+
break;
|
|
25913
|
+
}
|
|
25914
|
+
}
|
|
25915
|
+
}
|
|
25916
|
+
}
|
|
25917
|
+
}
|
|
25918
|
+
const allToolCallEvents = getToolCallEvents(data);
|
|
25919
|
+
const currentTurnToolCallEvents = knownIds ? allToolCallEvents?.filter(
|
|
25920
|
+
(evt) => evt.id !== void 0 && evt.id !== null && !knownIds.has(evt.id)
|
|
25921
|
+
) : allToolCallEvents;
|
|
25922
|
+
const baseSources = ctx.sources ?? [];
|
|
25923
|
+
const seenSourceUrls = new Set(
|
|
25924
|
+
baseSources.map((s) => s.url).filter((url) => !!url)
|
|
25925
|
+
);
|
|
25926
|
+
const toolEventSources = extractSourcesFromToolCallEvents(currentTurnToolCallEvents);
|
|
25927
|
+
const sources = [
|
|
25928
|
+
...baseSources,
|
|
25929
|
+
...toolEventSources.filter((s) => !s.url || !seenSourceUrls.has(s.url))
|
|
25930
|
+
].filter((source) => !source.url?.includes(MCP_R2_DOMAIN));
|
|
25931
|
+
const rowOpts = {
|
|
25932
|
+
conversationId: ctx.convId,
|
|
25933
|
+
role: "assistant",
|
|
25934
|
+
content,
|
|
25935
|
+
model: data.model || ctx.model || "",
|
|
25936
|
+
imageModel: ctx.imageModel || getImageModel(data),
|
|
25937
|
+
usage: convertUsageToStored(data),
|
|
25938
|
+
responseDuration,
|
|
25939
|
+
sources,
|
|
25940
|
+
thoughtProcess: finalizeThoughtProcess(ctx.thoughtProcess),
|
|
25941
|
+
thinking,
|
|
25942
|
+
wasStopped,
|
|
25943
|
+
parentMessageId,
|
|
25944
|
+
toolCallEvents: currentTurnToolCallEvents && currentTurnToolCallEvents.length > 0 ? currentTurnToolCallEvents : void 0,
|
|
25945
|
+
uniqueId: ctx.assistantUniqueId
|
|
25946
|
+
};
|
|
25947
|
+
if (!viaQueue) return upsertMessageOp(storageCtx, rowOpts);
|
|
25948
|
+
const { result } = await writeOrQueue(
|
|
25949
|
+
"createMessage",
|
|
25950
|
+
rowOpts,
|
|
25951
|
+
() => upsertMessageOp(storageCtx, rowOpts),
|
|
25952
|
+
() => makeSyntheticStoredMessage(rowOpts),
|
|
25953
|
+
ctx.userMessageQueueId ? [ctx.userMessageQueueId] : []
|
|
25954
|
+
);
|
|
25955
|
+
return result;
|
|
25956
|
+
},
|
|
25957
|
+
[storageCtx, getMessages, writeOrQueue]
|
|
25958
|
+
);
|
|
25959
|
+
const retirePendingTurn = useCallback4(async () => {
|
|
25960
|
+
const visible = activeResumeRef.current;
|
|
25961
|
+
if (visible && !visible.headless) {
|
|
25962
|
+
baseStop();
|
|
25963
|
+
await visible.settled;
|
|
25964
|
+
}
|
|
25965
|
+
if (retirementRef.current) return retirementRef.current;
|
|
25966
|
+
const active = activeResumeRef.current;
|
|
25967
|
+
if (active && !active.headless) return "Resume already in progress";
|
|
25968
|
+
const pending = pendingResumeRef.current;
|
|
25969
|
+
if (!pending) return null;
|
|
25970
|
+
if (!pending.userMessageUniqueId) {
|
|
25971
|
+
if (active?.context === pending) return null;
|
|
25972
|
+
if (!pending.partialData) {
|
|
25973
|
+
pendingResumeRef.current = null;
|
|
25974
|
+
return null;
|
|
25975
|
+
}
|
|
25976
|
+
}
|
|
25977
|
+
if (active?.context === pending) return "Resume already in progress";
|
|
25978
|
+
pendingResumeRef.current = null;
|
|
25979
|
+
retirementStopRequestedRef.current = false;
|
|
25980
|
+
const retirement = Promise.resolve().then(async () => {
|
|
25981
|
+
try {
|
|
25982
|
+
const data = pending.partialData;
|
|
25983
|
+
if (data && pending.assistantUniqueId) {
|
|
25984
|
+
const { content, thinking } = extractAssistantText(data);
|
|
25985
|
+
if (content || thinking || (getToolCallEvents(data)?.length ?? 0) > 0) {
|
|
25986
|
+
if (walletAddress && signMessage && !hasEncryptionKey(walletAddress)) {
|
|
25987
|
+
try {
|
|
25988
|
+
await requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner);
|
|
25989
|
+
} catch {
|
|
25990
|
+
}
|
|
25991
|
+
}
|
|
25992
|
+
await finalizeResumedRow(
|
|
25993
|
+
pending,
|
|
25994
|
+
data,
|
|
25995
|
+
true,
|
|
25996
|
+
(Date.now() - pending.startTime) / 1e3,
|
|
25997
|
+
true
|
|
25998
|
+
);
|
|
25999
|
+
}
|
|
26000
|
+
}
|
|
26001
|
+
if (pending.handle) baseCancel(pending.handle);
|
|
26002
|
+
return null;
|
|
26003
|
+
} catch (err) {
|
|
26004
|
+
pendingResumeRef.current = pending;
|
|
26005
|
+
if (retirementStopRequestedRef.current && pending.handle) {
|
|
26006
|
+
baseCancel(pending.handle);
|
|
26007
|
+
pendingResumeRef.current = { ...pending, handle: null };
|
|
26008
|
+
}
|
|
26009
|
+
return err instanceof Error ? err.message : "Failed to store detached message";
|
|
26010
|
+
}
|
|
26011
|
+
});
|
|
26012
|
+
retirementRef.current = retirement;
|
|
26013
|
+
try {
|
|
26014
|
+
return await retirement;
|
|
26015
|
+
} finally {
|
|
26016
|
+
if (retirementRef.current === retirement) {
|
|
26017
|
+
retirementRef.current = null;
|
|
26018
|
+
retirementStopRequestedRef.current = false;
|
|
26019
|
+
}
|
|
26020
|
+
}
|
|
26021
|
+
}, [baseCancel, baseStop, finalizeResumedRow, walletAddress, signMessage, embeddedWalletSigner]);
|
|
25628
26022
|
const sendMessage = useCallback4(
|
|
25629
26023
|
async (args) => {
|
|
25630
26024
|
const {
|
|
@@ -25676,7 +26070,11 @@ function useChatStorage(options) {
|
|
|
25676
26070
|
maskForCall: (text14) => redactor ? redactor.maskText(text14) : text14
|
|
25677
26071
|
};
|
|
25678
26072
|
};
|
|
25679
|
-
|
|
26073
|
+
const retirementError = await retirePendingTurn();
|
|
26074
|
+
if (retirementError) {
|
|
26075
|
+
if (!skipStorage) return { data: null, error: retirementError };
|
|
26076
|
+
getLogger().warn("[useChatStorage] detached partial not saved:", retirementError);
|
|
26077
|
+
}
|
|
25680
26078
|
const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${uuidv77()}` : void 0);
|
|
25681
26079
|
const embedToolText = (text14, mask, masked, token) => {
|
|
25682
26080
|
const opts = {
|
|
@@ -26200,6 +26598,7 @@ function useChatStorage(options) {
|
|
|
26200
26598
|
handle: detachedResult.resume ?? null,
|
|
26201
26599
|
convId,
|
|
26202
26600
|
userMessageUniqueId: storedUserMessage.uniqueId,
|
|
26601
|
+
userMessageQueueId: userMsgQueueId,
|
|
26203
26602
|
assistantUniqueId: rowId,
|
|
26204
26603
|
model,
|
|
26205
26604
|
imageModel,
|
|
@@ -26426,6 +26825,7 @@ function useChatStorage(options) {
|
|
|
26426
26825
|
getMessages,
|
|
26427
26826
|
storageCtx,
|
|
26428
26827
|
baseSendMessage,
|
|
26828
|
+
retirePendingTurn,
|
|
26429
26829
|
embedMessageAsync,
|
|
26430
26830
|
minContentLength,
|
|
26431
26831
|
walletAddress,
|
|
@@ -26440,72 +26840,9 @@ function useChatStorage(options) {
|
|
|
26440
26840
|
onPiiRedacted
|
|
26441
26841
|
]
|
|
26442
26842
|
);
|
|
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
26843
|
const resumeStream2 = useCallback4(
|
|
26507
26844
|
async (handleOverride, opts) => {
|
|
26508
|
-
if (isResumingRef.current) {
|
|
26845
|
+
if (isResumingRef.current || retirementRef.current) {
|
|
26509
26846
|
return { data: null, error: "Resume already in progress", assistantMessage: null };
|
|
26510
26847
|
}
|
|
26511
26848
|
const pending = pendingResumeRef.current;
|
|
@@ -26534,6 +26871,7 @@ function useChatStorage(options) {
|
|
|
26534
26871
|
if (pendingResumeRef.current === rctx) pendingResumeRef.current = null;
|
|
26535
26872
|
};
|
|
26536
26873
|
const safeFinalize = async (data, wasStopped, responseDuration) => {
|
|
26874
|
+
rctx.partialData = data;
|
|
26537
26875
|
try {
|
|
26538
26876
|
return { message: await finalizeResumedRow(rctx, data, wasStopped, responseDuration) };
|
|
26539
26877
|
} catch (writeErr) {
|
|
@@ -26543,6 +26881,13 @@ function useChatStorage(options) {
|
|
|
26543
26881
|
}
|
|
26544
26882
|
};
|
|
26545
26883
|
isResumingRef.current = true;
|
|
26884
|
+
let markSettled = () => {
|
|
26885
|
+
};
|
|
26886
|
+
const settled = new Promise((resolve) => {
|
|
26887
|
+
markSettled = resolve;
|
|
26888
|
+
});
|
|
26889
|
+
const activeResume = { context: rctx, headless: opts?.headless === true, settled };
|
|
26890
|
+
activeResumeRef.current = activeResume;
|
|
26546
26891
|
try {
|
|
26547
26892
|
const result = await baseResumeStream(handle, { headless: opts?.headless });
|
|
26548
26893
|
const responseDuration = (Date.now() - rctx.startTime) / 1e3;
|
|
@@ -26619,11 +26964,17 @@ function useChatStorage(options) {
|
|
|
26619
26964
|
throw err;
|
|
26620
26965
|
} finally {
|
|
26621
26966
|
isResumingRef.current = false;
|
|
26967
|
+
if (activeResumeRef.current === activeResume) activeResumeRef.current = null;
|
|
26968
|
+
markSettled();
|
|
26622
26969
|
}
|
|
26623
26970
|
},
|
|
26624
26971
|
[baseResumeStream, currentConversationId, finalizeResumedRow, embedMessageAsync]
|
|
26625
26972
|
);
|
|
26626
26973
|
const stop = useCallback4(() => {
|
|
26974
|
+
if (retirementRef.current) {
|
|
26975
|
+
retirementStopRequestedRef.current = true;
|
|
26976
|
+
return;
|
|
26977
|
+
}
|
|
26627
26978
|
const pending = pendingResumeRef.current;
|
|
26628
26979
|
if (pending && pending.assistantUniqueId && !isResumingRef.current) {
|
|
26629
26980
|
const finalize = pending;
|