@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.cjs
CHANGED
|
@@ -122,6 +122,18 @@ var init_clientConfig = __esm({
|
|
|
122
122
|
}
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
+
// src/lib/taskType.ts
|
|
126
|
+
function taskTypeHeader(taskType) {
|
|
127
|
+
return taskType ? { [TASK_TYPE_HEADER]: taskType } : {};
|
|
128
|
+
}
|
|
129
|
+
var TASK_TYPE_HEADER;
|
|
130
|
+
var init_taskType = __esm({
|
|
131
|
+
"src/lib/taskType.ts"() {
|
|
132
|
+
"use strict";
|
|
133
|
+
TASK_TYPE_HEADER = "X-Anuma-Task-Type";
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
125
137
|
// src/lib/pii/patterns.ts
|
|
126
138
|
function luhnCheck(digits) {
|
|
127
139
|
let sum = 0;
|
|
@@ -766,18 +778,6 @@ var init_internalFlowMarker = __esm({
|
|
|
766
778
|
}
|
|
767
779
|
});
|
|
768
780
|
|
|
769
|
-
// src/lib/taskType.ts
|
|
770
|
-
function taskTypeHeader(taskType) {
|
|
771
|
-
return taskType ? { [TASK_TYPE_HEADER]: taskType } : {};
|
|
772
|
-
}
|
|
773
|
-
var TASK_TYPE_HEADER;
|
|
774
|
-
var init_taskType = __esm({
|
|
775
|
-
"src/lib/taskType.ts"() {
|
|
776
|
-
"use strict";
|
|
777
|
-
TASK_TYPE_HEADER = "X-Anuma-Task-Type";
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
|
|
781
781
|
// src/lib/memory/portalLlm.ts
|
|
782
782
|
function defaultBaseUrl() {
|
|
783
783
|
return typeof process !== "undefined" && process.env?.ANUMA_PORTAL_BASE_URL || BASE_URL;
|
|
@@ -5218,6 +5218,7 @@ var getApiV1Models = (options) => (options?.client ?? client).get({ url: "/api/v
|
|
|
5218
5218
|
|
|
5219
5219
|
// src/lib/memoryEngine/generate.ts
|
|
5220
5220
|
init_clientConfig();
|
|
5221
|
+
init_taskType();
|
|
5221
5222
|
var EMBED_MAX_ATTEMPTS = 4;
|
|
5222
5223
|
var DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS = 15e3;
|
|
5223
5224
|
var DEFAULT_EMBEDDING_TOKEN_TIMEOUT_MS = 1e4;
|
|
@@ -5315,7 +5316,10 @@ async function embedOne(text14, options, outer) {
|
|
|
5315
5316
|
const cached = cache.get(text14);
|
|
5316
5317
|
if (cached) return Array.from(cached);
|
|
5317
5318
|
}
|
|
5318
|
-
const headers =
|
|
5319
|
+
const headers = {
|
|
5320
|
+
...await resolveAuthHeaders(options, outer),
|
|
5321
|
+
...taskTypeHeader(options.taskType)
|
|
5322
|
+
};
|
|
5319
5323
|
const response = await withEmbeddingRetry(
|
|
5320
5324
|
() => withDeadline(
|
|
5321
5325
|
(signal) => postApiV1Embeddings({
|
|
@@ -5410,7 +5414,10 @@ async function embedMany(texts, options, outer) {
|
|
|
5410
5414
|
if (uncachedTexts.length === 0) {
|
|
5411
5415
|
return results;
|
|
5412
5416
|
}
|
|
5413
|
-
const headers =
|
|
5417
|
+
const headers = {
|
|
5418
|
+
...await resolveAuthHeaders(options, outer),
|
|
5419
|
+
...taskTypeHeader(options.taskType)
|
|
5420
|
+
};
|
|
5414
5421
|
if (outer?.aborted) throw outer.reason;
|
|
5415
5422
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5416
5423
|
let newEmbeddings;
|
|
@@ -15149,6 +15156,50 @@ function applyMMR(candidates, k, lambda = 0.5) {
|
|
|
15149
15156
|
return selected;
|
|
15150
15157
|
}
|
|
15151
15158
|
|
|
15159
|
+
// src/lib/memory/recallTelemetry.ts
|
|
15160
|
+
function notifyMemoryCallback(callback, value) {
|
|
15161
|
+
try {
|
|
15162
|
+
callback?.(value);
|
|
15163
|
+
} catch {
|
|
15164
|
+
return;
|
|
15165
|
+
}
|
|
15166
|
+
}
|
|
15167
|
+
function factRecallDiagnostics(scores, elapsedMs, options = {}) {
|
|
15168
|
+
return {
|
|
15169
|
+
usedBudget: "low",
|
|
15170
|
+
reranked: false,
|
|
15171
|
+
candidateCount: options.candidateCount ?? scores.length,
|
|
15172
|
+
...options.vaultSize !== void 0 && { vaultSize: options.vaultSize },
|
|
15173
|
+
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
15174
|
+
...options.vaultRowsDecrypted !== void 0 && {
|
|
15175
|
+
vaultRowsDecrypted: options.vaultRowsDecrypted
|
|
15176
|
+
},
|
|
15177
|
+
...options.vaultRowsEmbedded !== void 0 && {
|
|
15178
|
+
vaultRowsEmbedded: options.vaultRowsEmbedded
|
|
15179
|
+
},
|
|
15180
|
+
factCount: scores.length,
|
|
15181
|
+
chunkCount: 0,
|
|
15182
|
+
admittedCount: scores.length,
|
|
15183
|
+
topScore: scores.length ? Math.max(...scores) : -1,
|
|
15184
|
+
lowestAdmittedScore: scores.length ? Math.min(...scores) : -1,
|
|
15185
|
+
minScoreApplied: options.minScore ?? -1,
|
|
15186
|
+
truncated: options.truncated ?? false,
|
|
15187
|
+
graphLaneCount: 0,
|
|
15188
|
+
temporalLaneCount: 0,
|
|
15189
|
+
emptyReason: scores.length ? "" : options.vaultSize === 0 ? "vault-empty" : "no-candidates",
|
|
15190
|
+
timings: {
|
|
15191
|
+
total: elapsedMs,
|
|
15192
|
+
prep: 0,
|
|
15193
|
+
factLane: elapsedMs,
|
|
15194
|
+
rerank: 0,
|
|
15195
|
+
queryEmbed: options.queryEmbedMs ?? 0,
|
|
15196
|
+
chunkLane: 0,
|
|
15197
|
+
fuse: 0
|
|
15198
|
+
},
|
|
15199
|
+
degraded: options.embeddingsUnavailable ? ["embeddings-unavailable"] : []
|
|
15200
|
+
};
|
|
15201
|
+
}
|
|
15202
|
+
|
|
15152
15203
|
// src/lib/memory/recency.ts
|
|
15153
15204
|
var DAY_MS2 = 1e3 * 60 * 60 * 24;
|
|
15154
15205
|
var DEFAULT_PER_YEAR_DECAY = 0.2;
|
|
@@ -15841,6 +15892,7 @@ function rankVaultMemories(_query, queryEmbedding, items, options) {
|
|
|
15841
15892
|
}
|
|
15842
15893
|
filtered.sort((a, b) => b.similarity - a.similarity);
|
|
15843
15894
|
}
|
|
15895
|
+
notifyMemoryCallback(options?.onCandidateCount, filtered.length);
|
|
15844
15896
|
const itemById = new Map(items.map((i) => [i.id, i]));
|
|
15845
15897
|
return filtered.slice(0, limit).map((r) => resultFromItem(itemById.get(r.uniqueId), r.similarity));
|
|
15846
15898
|
}
|
|
@@ -16823,6 +16875,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
16823
16875
|
const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
16824
16876
|
limit,
|
|
16825
16877
|
minSimilarity,
|
|
16878
|
+
onCandidateCount: searchOptions?.onCandidateCount,
|
|
16826
16879
|
...searchOptions?.supersessionBoost !== void 0 && {
|
|
16827
16880
|
supersessionBoost: searchOptions.supersessionBoost
|
|
16828
16881
|
},
|
|
@@ -16924,16 +16977,20 @@ var DEFAULT_SCOPE = "private";
|
|
|
16924
16977
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
16925
16978
|
var DEFAULT_CONSOLIDATE_TOP_K = 20;
|
|
16926
16979
|
async function retain(content, ctx, options = {}) {
|
|
16980
|
+
const embeddingOptions = {
|
|
16981
|
+
...ctx.embeddingOptions,
|
|
16982
|
+
taskType: "memory_retain_embed"
|
|
16983
|
+
};
|
|
16927
16984
|
return retainWithPersistence(
|
|
16928
16985
|
content,
|
|
16929
16986
|
{
|
|
16930
|
-
embeddingOptions
|
|
16987
|
+
embeddingOptions,
|
|
16931
16988
|
vaultCache: ctx.vaultCache,
|
|
16932
16989
|
persistence: {
|
|
16933
16990
|
prepare: (query, searchOptions) => prepareVaultCandidates(
|
|
16934
16991
|
query,
|
|
16935
16992
|
ctx.vaultCtx,
|
|
16936
|
-
|
|
16993
|
+
embeddingOptions,
|
|
16937
16994
|
ctx.vaultCache,
|
|
16938
16995
|
searchOptions
|
|
16939
16996
|
),
|
|
@@ -18087,7 +18144,17 @@ function parseVerdict(parsed) {
|
|
|
18087
18144
|
|
|
18088
18145
|
// src/lib/memory/decayWorker.ts
|
|
18089
18146
|
init_logger();
|
|
18090
|
-
|
|
18147
|
+
function emptyResult() {
|
|
18148
|
+
return {
|
|
18149
|
+
archived: 0,
|
|
18150
|
+
deleted: 0,
|
|
18151
|
+
scanned: 0,
|
|
18152
|
+
ruleDriven: { archived: 0, deleted: 0 },
|
|
18153
|
+
classifierDriven: { archived: 0, deleted: 0 },
|
|
18154
|
+
classifierCalls: 0,
|
|
18155
|
+
classifierCapHits: 0
|
|
18156
|
+
};
|
|
18157
|
+
}
|
|
18091
18158
|
var DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP = 20;
|
|
18092
18159
|
function resolveNow(now) {
|
|
18093
18160
|
if (typeof now === "function") return now();
|
|
@@ -18126,42 +18193,45 @@ function createDecaySweeper(options) {
|
|
|
18126
18193
|
let disposed = false;
|
|
18127
18194
|
async function verdictFor(input, now, sweep) {
|
|
18128
18195
|
const ruleVerdict = classifyDecay(input, now, policy);
|
|
18129
|
-
|
|
18130
|
-
if (
|
|
18196
|
+
const rule = { verdict: ruleVerdict, source: "ruleDriven" };
|
|
18197
|
+
if (ruleVerdict !== "keep") return rule;
|
|
18198
|
+
if (!classifier || !isBorderline(input)) return rule;
|
|
18131
18199
|
if (input.id) {
|
|
18132
18200
|
const cached = classifierCache.get(input.id);
|
|
18133
|
-
if (cached && cached.activityAt === lastActivityAt(input))
|
|
18201
|
+
if (cached && cached.activityAt === lastActivityAt(input))
|
|
18202
|
+
return { verdict: cached.verdict, source: "classifierDriven" };
|
|
18134
18203
|
}
|
|
18135
18204
|
if (sweep.classifierCalls >= maxClassifierCalls) {
|
|
18205
|
+
sweep.classifierCapHits++;
|
|
18136
18206
|
if (!sweep.ceilingLogged) {
|
|
18137
18207
|
sweep.ceilingLogged = true;
|
|
18138
18208
|
getLogger().warn(
|
|
18139
18209
|
`[memory/decay] classifier per-sweep ceiling (${maxClassifierCalls}) reached; remaining borderline rows use the rule verdict this sweep`
|
|
18140
18210
|
);
|
|
18141
18211
|
}
|
|
18142
|
-
return
|
|
18212
|
+
return rule;
|
|
18143
18213
|
}
|
|
18144
18214
|
sweep.classifierCalls++;
|
|
18145
18215
|
try {
|
|
18146
18216
|
const verdict = await classifier.classify(input, ruleVerdict, now);
|
|
18147
18217
|
if (input.id) classifierCache.set(input.id, { activityAt: lastActivityAt(input), verdict });
|
|
18148
|
-
return verdict;
|
|
18218
|
+
return { verdict, source: "classifierDriven" };
|
|
18149
18219
|
} catch (err) {
|
|
18150
18220
|
getLogger().warn(
|
|
18151
18221
|
`[memory/decay] classifier failed; falling back to rule verdict: ${err instanceof Error ? err.message : String(err)}`
|
|
18152
18222
|
);
|
|
18153
|
-
return
|
|
18223
|
+
return rule;
|
|
18154
18224
|
}
|
|
18155
18225
|
}
|
|
18156
18226
|
async function runSweep() {
|
|
18157
|
-
if (disposed) return
|
|
18227
|
+
if (disposed) return emptyResult();
|
|
18158
18228
|
const now = resolveNow(options.now);
|
|
18159
18229
|
let candidates;
|
|
18160
18230
|
try {
|
|
18161
18231
|
candidates = await getDecayCandidatesRawOp(vaultCtx);
|
|
18162
18232
|
} catch (err) {
|
|
18163
18233
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
18164
|
-
return
|
|
18234
|
+
return emptyResult();
|
|
18165
18235
|
}
|
|
18166
18236
|
if (classifierCache.size > 0) {
|
|
18167
18237
|
const liveIds = new Set(candidates.map((c) => c.uniqueId));
|
|
@@ -18169,33 +18239,40 @@ function createDecaySweeper(options) {
|
|
|
18169
18239
|
if (!liveIds.has(id)) classifierCache.delete(id);
|
|
18170
18240
|
}
|
|
18171
18241
|
}
|
|
18172
|
-
const sweep = { classifierCalls: 0, ceilingLogged: false };
|
|
18242
|
+
const sweep = { classifierCalls: 0, classifierCapHits: 0, ceilingLogged: false };
|
|
18173
18243
|
const toArchive = [];
|
|
18174
18244
|
const toDelete = [];
|
|
18175
18245
|
for (const c of candidates) {
|
|
18176
|
-
const verdict = await verdictFor(toDecayInput(c), now, sweep);
|
|
18177
|
-
if (verdict === "archive") toArchive.push(c);
|
|
18178
|
-
else if (verdict === "delete") toDelete.push(c);
|
|
18179
|
-
}
|
|
18180
|
-
|
|
18181
|
-
|
|
18246
|
+
const { verdict, source } = await verdictFor(toDecayInput(c), now, sweep);
|
|
18247
|
+
if (verdict === "archive") toArchive.push({ candidate: c, source });
|
|
18248
|
+
else if (verdict === "delete") toDelete.push({ candidate: c, source });
|
|
18249
|
+
}
|
|
18250
|
+
const result = emptyResult();
|
|
18251
|
+
result.scanned = candidates.length;
|
|
18252
|
+
result.classifierCalls = sweep.classifierCalls;
|
|
18253
|
+
result.classifierCapHits = sweep.classifierCapHits;
|
|
18182
18254
|
try {
|
|
18183
|
-
for (const c of toArchive) {
|
|
18255
|
+
for (const { candidate: c, source } of toArchive) {
|
|
18184
18256
|
const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
|
|
18185
18257
|
now,
|
|
18186
18258
|
expectedUpdatedAt: c.updatedAt,
|
|
18187
18259
|
expectedLastObservedAt: c.lastObservedAt ?? null
|
|
18188
18260
|
});
|
|
18189
|
-
if (ok)
|
|
18261
|
+
if (ok) {
|
|
18262
|
+
result.archived++;
|
|
18263
|
+
result[source].archived++;
|
|
18264
|
+
}
|
|
18190
18265
|
}
|
|
18191
|
-
for (const c of toDelete) {
|
|
18266
|
+
for (const { candidate: c, source } of toDelete) {
|
|
18192
18267
|
const ok = await hardDeleteDecayedOp(vaultCtx, c.uniqueId, { hardDeleteWindowMs, now });
|
|
18193
|
-
if (ok)
|
|
18268
|
+
if (ok) {
|
|
18269
|
+
result.deleted++;
|
|
18270
|
+
result[source].deleted++;
|
|
18271
|
+
}
|
|
18194
18272
|
}
|
|
18195
18273
|
} catch (err) {
|
|
18196
18274
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
18197
18275
|
}
|
|
18198
|
-
const result = { archived, deleted, scanned: candidates.length };
|
|
18199
18276
|
onSwept?.(result);
|
|
18200
18277
|
return result;
|
|
18201
18278
|
}
|
|
@@ -18800,6 +18877,10 @@ async function recall(query, ctx, options = {}) {
|
|
|
18800
18877
|
const flags = flagsForBudget(usedBudget);
|
|
18801
18878
|
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
18802
18879
|
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
18880
|
+
const embeddingOptions = {
|
|
18881
|
+
...ctx.embeddingOptions,
|
|
18882
|
+
taskType: "memory_recall_embed"
|
|
18883
|
+
};
|
|
18803
18884
|
const t0 = nowMs2();
|
|
18804
18885
|
let prepMs = 0;
|
|
18805
18886
|
let factLaneMs = 0;
|
|
@@ -18895,7 +18976,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
18895
18976
|
let sharedEmbedMs = 0;
|
|
18896
18977
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
18897
18978
|
needsChunkEmbedding ? generateEmbedding(query, {
|
|
18898
|
-
...
|
|
18979
|
+
...embeddingOptions,
|
|
18899
18980
|
totalTimeoutMs: queryEmbedTotalTimeoutMs
|
|
18900
18981
|
}).finally(() => {
|
|
18901
18982
|
sharedEmbedMs = nowMs2() - prepStart;
|
|
@@ -18953,7 +19034,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
18953
19034
|
} = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
|
|
18954
19035
|
searchQuery,
|
|
18955
19036
|
ctx.vaultCtx,
|
|
18956
|
-
|
|
19037
|
+
embeddingOptions,
|
|
18957
19038
|
ctx.vaultCache,
|
|
18958
19039
|
searchOptions
|
|
18959
19040
|
)))(query, {
|
|
@@ -19319,7 +19400,7 @@ function isDumpQuery(query) {
|
|
|
19319
19400
|
async function listRecentFacts(ctx, limit, toolOptions) {
|
|
19320
19401
|
const store = toolOptions?.memoryStore;
|
|
19321
19402
|
const vaultCtx = ctx.vaultCtx;
|
|
19322
|
-
if (!vaultCtx && !store) return [];
|
|
19403
|
+
if (!vaultCtx && !store) return { memories: [], truncated: false };
|
|
19323
19404
|
const read = (ids) => store ? store.list({ memoryIds: ids }) : getVaultMemoriesByIdsOp(vaultCtx, ids);
|
|
19324
19405
|
const filters = {
|
|
19325
19406
|
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
@@ -19330,34 +19411,47 @@ async function listRecentFacts(ctx, limit, toolOptions) {
|
|
|
19330
19411
|
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId }
|
|
19331
19412
|
});
|
|
19332
19413
|
const readable = [];
|
|
19414
|
+
const readLimit = limit + 1;
|
|
19415
|
+
let batchLimit = limit;
|
|
19333
19416
|
let start = 0;
|
|
19334
|
-
|
|
19417
|
+
let projected = 0;
|
|
19418
|
+
let exhausted = false;
|
|
19419
|
+
for (let size = readLimit; readable.length < readLimit; size *= 2) {
|
|
19335
19420
|
const ordered = await project(size);
|
|
19336
|
-
|
|
19337
|
-
|
|
19421
|
+
projected = ordered.length;
|
|
19422
|
+
exhausted = !store || ordered.length < size;
|
|
19423
|
+
for (let i = start; i < ordered.length && readable.length < readLimit; ) {
|
|
19424
|
+
const batch = ordered.slice(i, i + batchLimit).map((p) => p.uniqueId);
|
|
19338
19425
|
const byId = new Map((await read(batch)).map((m) => [m.uniqueId, m]));
|
|
19426
|
+
const previousCount = readable.length;
|
|
19339
19427
|
for (const id of batch) {
|
|
19340
19428
|
const m = byId.get(id);
|
|
19341
19429
|
if (m && !isEncrypted(m.content)) readable.push(m);
|
|
19342
|
-
if (readable.length >=
|
|
19430
|
+
if (readable.length >= readLimit) break;
|
|
19343
19431
|
}
|
|
19432
|
+
batchLimit = readable.length > previousCount ? Math.min(limit, readLimit - readable.length) : limit;
|
|
19433
|
+
i += batch.length;
|
|
19344
19434
|
}
|
|
19345
|
-
if (
|
|
19435
|
+
if (exhausted) break;
|
|
19346
19436
|
start = ordered.length;
|
|
19347
19437
|
}
|
|
19348
|
-
return
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
|
|
19438
|
+
return {
|
|
19439
|
+
memories: readable.slice(0, limit).map((m) => ({
|
|
19440
|
+
id: m.uniqueId,
|
|
19441
|
+
kind: "fact",
|
|
19442
|
+
content: m.content,
|
|
19443
|
+
score: 0,
|
|
19444
|
+
folderId: m.folderId,
|
|
19445
|
+
eventTimeStart: m.eventTimeStart,
|
|
19446
|
+
eventTimeEnd: m.eventTimeEnd,
|
|
19447
|
+
eventTimeKind: m.eventTimeKind,
|
|
19448
|
+
factType: m.factType,
|
|
19449
|
+
createdAt: m.createdAt,
|
|
19450
|
+
updatedAt: m.updatedAt
|
|
19451
|
+
})),
|
|
19452
|
+
...exhausted && { vaultSize: projected },
|
|
19453
|
+
truncated: readable.length > limit
|
|
19454
|
+
};
|
|
19361
19455
|
}
|
|
19362
19456
|
function createRecallTool(ctx, toolOptions, callbacks) {
|
|
19363
19457
|
if (toolOptions?.memoryStore && toolOptions.folderId !== void 0)
|
|
@@ -19396,7 +19490,11 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
19396
19490
|
},
|
|
19397
19491
|
executor: async (args) => {
|
|
19398
19492
|
if (typeof args.query !== "string" || args.query.length === 0) {
|
|
19399
|
-
|
|
19493
|
+
const error = new Error(
|
|
19494
|
+
"recall_memory: `query` is required and must be a non-empty string."
|
|
19495
|
+
);
|
|
19496
|
+
notifyMemoryCallback(callbacks?.onError, error);
|
|
19497
|
+
throw error;
|
|
19400
19498
|
}
|
|
19401
19499
|
const query = args.query;
|
|
19402
19500
|
const now = Date.now();
|
|
@@ -19424,10 +19522,17 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
19424
19522
|
RECALL_MAX_MEMORIES_PER_CONVERSATION - conversationMemories
|
|
19425
19523
|
);
|
|
19426
19524
|
const effectiveLimit = Math.min(requestLimit, remainingTurnBudget, remainingConvBudget);
|
|
19525
|
+
const truncatedByBudget = effectiveLimit < requestLimit;
|
|
19526
|
+
if (truncatedByBudget) {
|
|
19527
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
19528
|
+
requestedLimit: requestLimit,
|
|
19529
|
+
effectiveLimit,
|
|
19530
|
+
truncatedByBudget
|
|
19531
|
+
});
|
|
19532
|
+
}
|
|
19427
19533
|
if (effectiveLimit <= 0) {
|
|
19428
19534
|
return VOLUME_LIMIT_NOTICE;
|
|
19429
19535
|
}
|
|
19430
|
-
const truncatedByBudget = effectiveLimit < requestLimit;
|
|
19431
19536
|
turnMemories += effectiveLimit;
|
|
19432
19537
|
conversationMemories += effectiveLimit;
|
|
19433
19538
|
let surfaced = 0;
|
|
@@ -19436,7 +19541,27 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
19436
19541
|
const wantsRecent = args.sort === "recent" && defaultTypes.includes("fact") && (ctx.vaultCtx !== void 0 || toolOptions?.memoryStore !== void 0);
|
|
19437
19542
|
let result;
|
|
19438
19543
|
if (wantsRecent) {
|
|
19439
|
-
|
|
19544
|
+
const start = Date.now();
|
|
19545
|
+
const recent = await listRecentFacts(ctx, effectiveLimit, toolOptions);
|
|
19546
|
+
result = recent;
|
|
19547
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, {
|
|
19548
|
+
...factRecallDiagnostics(
|
|
19549
|
+
result.memories.map((m) => m.score),
|
|
19550
|
+
Date.now() - start,
|
|
19551
|
+
{
|
|
19552
|
+
truncated: recent.truncated,
|
|
19553
|
+
...recent.vaultSize !== void 0 && { vaultSize: recent.vaultSize }
|
|
19554
|
+
}
|
|
19555
|
+
),
|
|
19556
|
+
truncatedByBudget
|
|
19557
|
+
});
|
|
19558
|
+
if (recent.truncated && !truncatedByBudget) {
|
|
19559
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
19560
|
+
requestedLimit: requestLimit,
|
|
19561
|
+
effectiveLimit,
|
|
19562
|
+
truncatedByBudget
|
|
19563
|
+
});
|
|
19564
|
+
}
|
|
19440
19565
|
} else {
|
|
19441
19566
|
let subQueries;
|
|
19442
19567
|
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
@@ -19448,6 +19573,14 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
19448
19573
|
const recallOpts = {
|
|
19449
19574
|
onDiagnostics: (d) => {
|
|
19450
19575
|
recallDegraded = d.degraded;
|
|
19576
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, { ...d, truncatedByBudget });
|
|
19577
|
+
if (d.truncated && !truncatedByBudget) {
|
|
19578
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
19579
|
+
requestedLimit: requestLimit,
|
|
19580
|
+
effectiveLimit,
|
|
19581
|
+
truncatedByBudget
|
|
19582
|
+
});
|
|
19583
|
+
}
|
|
19451
19584
|
},
|
|
19452
19585
|
types: defaultTypes,
|
|
19453
19586
|
limit: effectiveLimit,
|
|
@@ -19491,6 +19624,7 @@ ${TRUNCATION_NOTICE}` : formatted;
|
|
|
19491
19624
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
19492
19625
|
const wrapped = new Error(`recall_memory: search failed \u2014 ${message}`);
|
|
19493
19626
|
wrapped.cause = error;
|
|
19627
|
+
notifyMemoryCallback(callbacks?.onError, wrapped);
|
|
19494
19628
|
throw wrapped;
|
|
19495
19629
|
} finally {
|
|
19496
19630
|
const unused = effectiveLimit - surfaced;
|
|
@@ -19732,6 +19866,18 @@ When a memory refers to one of these, reuse the EXACT existing name (same spelli
|
|
|
19732
19866
|
` : "";
|
|
19733
19867
|
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
|
19734
19868
|
const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
|
|
19869
|
+
const start = Date.now();
|
|
19870
|
+
let attempts = 0;
|
|
19871
|
+
let failure;
|
|
19872
|
+
const reportBatch = (unansweredCount) => {
|
|
19873
|
+
notifyMemoryCallback(options.onBatch, {
|
|
19874
|
+
memoryIds: batch.map((m) => m.id),
|
|
19875
|
+
attempts,
|
|
19876
|
+
durationMs: Date.now() - start,
|
|
19877
|
+
unansweredCount,
|
|
19878
|
+
...failure && { failure }
|
|
19879
|
+
});
|
|
19880
|
+
};
|
|
19735
19881
|
const rows = [];
|
|
19736
19882
|
for (const m of batch) {
|
|
19737
19883
|
const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
|
|
@@ -19753,6 +19899,12 @@ ${listing}
|
|
|
19753
19899
|
|
|
19754
19900
|
List each memory's named entities.`,
|
|
19755
19901
|
tag: "memory/topics",
|
|
19902
|
+
onAttempt: (attempt) => {
|
|
19903
|
+
attempts = attempt.attempt;
|
|
19904
|
+
},
|
|
19905
|
+
onFailure: (value) => {
|
|
19906
|
+
failure = value;
|
|
19907
|
+
},
|
|
19756
19908
|
extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
|
|
19757
19909
|
...options.fetchFn && { fetchFn: options.fetchFn },
|
|
19758
19910
|
...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
|
|
@@ -19761,6 +19913,7 @@ List each memory's named entities.`,
|
|
|
19761
19913
|
...options.backoffMs && { backoffMs: options.backoffMs }
|
|
19762
19914
|
});
|
|
19763
19915
|
if (parsed === null) {
|
|
19916
|
+
reportBatch(batch.length);
|
|
19764
19917
|
getLogger().warn(
|
|
19765
19918
|
`[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
|
|
19766
19919
|
);
|
|
@@ -19769,6 +19922,7 @@ List each memory's named entities.`,
|
|
|
19769
19922
|
const validIds = new Set(batch.map((m) => m.id));
|
|
19770
19923
|
const byId = parseTopicResponse(parsed, validIds);
|
|
19771
19924
|
if (byId === null) {
|
|
19925
|
+
reportBatch(batch.length);
|
|
19772
19926
|
getLogger().warn(
|
|
19773
19927
|
`[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
|
|
19774
19928
|
);
|
|
@@ -19781,6 +19935,7 @@ List each memory's named entities.`,
|
|
|
19781
19935
|
}
|
|
19782
19936
|
out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
|
|
19783
19937
|
}
|
|
19938
|
+
reportBatch(batch.filter((m) => !byId.has(m.id)).length);
|
|
19784
19939
|
}
|
|
19785
19940
|
return out;
|
|
19786
19941
|
}
|
|
@@ -19819,6 +19974,7 @@ function isDegradedTopicSkip(reason) {
|
|
|
19819
19974
|
return DEGRADED_TOPIC_SKIP[reason] === true;
|
|
19820
19975
|
}
|
|
19821
19976
|
async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
19977
|
+
const start = Date.now();
|
|
19822
19978
|
const entityCtx = ctx.entityCtx;
|
|
19823
19979
|
if (!entityCtx) {
|
|
19824
19980
|
throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
|
|
@@ -19859,7 +20015,18 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
19859
20015
|
skip(id, "unreadable");
|
|
19860
20016
|
}
|
|
19861
20017
|
}
|
|
19862
|
-
const
|
|
20018
|
+
const batches = [];
|
|
20019
|
+
const llmFailures = /* @__PURE__ */ new Map();
|
|
20020
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, {
|
|
20021
|
+
...options,
|
|
20022
|
+
onBatch: (batch) => {
|
|
20023
|
+
batches.push(batch);
|
|
20024
|
+
if (batch.failure) {
|
|
20025
|
+
for (const id of batch.memoryIds) llmFailures.set(id, batch.failure);
|
|
20026
|
+
}
|
|
20027
|
+
notifyMemoryCallback(options.onBatch, batch);
|
|
20028
|
+
}
|
|
20029
|
+
});
|
|
19863
20030
|
const toStamp = [];
|
|
19864
20031
|
for (const input of inputs) {
|
|
19865
20032
|
const entities = entitiesByMemory.get(input.id);
|
|
@@ -19890,7 +20057,16 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
19890
20057
|
entitiesByMemory.delete(id);
|
|
19891
20058
|
}
|
|
19892
20059
|
}
|
|
19893
|
-
return {
|
|
20060
|
+
return {
|
|
20061
|
+
entitiesByMemory,
|
|
20062
|
+
stampedIds,
|
|
20063
|
+
skippedIds,
|
|
20064
|
+
skippedReasons,
|
|
20065
|
+
batchCount: batches.length,
|
|
20066
|
+
durationMs: Date.now() - start,
|
|
20067
|
+
batches,
|
|
20068
|
+
llmFailures
|
|
20069
|
+
};
|
|
19894
20070
|
}
|
|
19895
20071
|
|
|
19896
20072
|
// src/lib/memory/store/local.ts
|
|
@@ -20045,7 +20221,7 @@ function createLocalMemoryStore(options) {
|
|
|
20045
20221
|
search: (query, searchOptions) => searchVaultMemoriesWithSize(
|
|
20046
20222
|
query,
|
|
20047
20223
|
vaultCtx,
|
|
20048
|
-
options.embeddingOptions,
|
|
20224
|
+
{ ...options.embeddingOptions, taskType: "memory_recall_embed" },
|
|
20049
20225
|
vaultCache,
|
|
20050
20226
|
searchOptions
|
|
20051
20227
|
),
|
|
@@ -20709,6 +20885,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
20709
20885
|
const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
|
|
20710
20886
|
const embed = (texts) => generateEmbeddings(texts, {
|
|
20711
20887
|
...embeddingOptions,
|
|
20888
|
+
taskType: mode === "retain" ? "memory_retain_embed" : "memory_recall_embed",
|
|
20712
20889
|
totalTimeoutMs: budgetMs
|
|
20713
20890
|
});
|
|
20714
20891
|
const embedFacets = async () => {
|
|
@@ -20957,7 +21134,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
20957
21134
|
const ranked = await rankPreparedVaultCandidates(
|
|
20958
21135
|
text14,
|
|
20959
21136
|
prepared,
|
|
20960
|
-
embeddingOptions,
|
|
21137
|
+
{ ...embeddingOptions, taskType: "memory_recall_embed" },
|
|
20961
21138
|
searchOptions
|
|
20962
21139
|
);
|
|
20963
21140
|
return {
|
|
@@ -20979,7 +21156,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
20979
21156
|
content,
|
|
20980
21157
|
{
|
|
20981
21158
|
persistence: port,
|
|
20982
|
-
embeddingOptions,
|
|
21159
|
+
embeddingOptions: { ...embeddingOptions, taskType: "memory_retain_embed" },
|
|
20983
21160
|
vaultCache: /* @__PURE__ */ new Map(),
|
|
20984
21161
|
normalizeEmbedding: storedVector
|
|
20985
21162
|
},
|
|
@@ -21356,6 +21533,7 @@ var MAX_BATCH = 50;
|
|
|
21356
21533
|
var MAX_QUERY_IDS = 1e3;
|
|
21357
21534
|
var MAX_QUERY_TOPICS = 100;
|
|
21358
21535
|
var MAX_QUERY_FILTER = 20;
|
|
21536
|
+
var GRAPH_LANE_ROWS = 256;
|
|
21359
21537
|
var RemoteMemoryPartialCreateError = class extends Error {
|
|
21360
21538
|
constructor(created, cause) {
|
|
21361
21539
|
super(`createMany stored ${created.length} memories before a batch failed`);
|
|
@@ -21451,7 +21629,11 @@ function createRemoteMemoryStore(options) {
|
|
|
21451
21629
|
const { persistence, embeddingOptions } = options;
|
|
21452
21630
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21453
21631
|
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
21454
|
-
const pipeline = createRemoteMemoryPipeline(
|
|
21632
|
+
const pipeline = createRemoteMemoryPipeline({
|
|
21633
|
+
...options,
|
|
21634
|
+
graphRanking: options.graphRanking ?? ((query, _traverse, recallOptions) => topicGraphRanking(query, recallOptions)),
|
|
21635
|
+
temporalRanking: options.temporalRanking ?? (() => Promise.resolve([]))
|
|
21636
|
+
});
|
|
21455
21637
|
const subscribers = /* @__PURE__ */ new Set();
|
|
21456
21638
|
const seen = /* @__PURE__ */ new Map();
|
|
21457
21639
|
let timer;
|
|
@@ -21483,6 +21665,36 @@ function createRemoteMemoryStore(options) {
|
|
|
21483
21665
|
const decrypted = (options2) => persistence.query(options2);
|
|
21484
21666
|
const metadata2 = (options2) => persistence.queryMetadata(options2);
|
|
21485
21667
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
21668
|
+
const memoriesByTopics = async (names) => {
|
|
21669
|
+
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
21670
|
+
const out = /* @__PURE__ */ new Map();
|
|
21671
|
+
const pages2 = await Promise.all(
|
|
21672
|
+
chunks2([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
21673
|
+
);
|
|
21674
|
+
for (const { memory } of pages2.flat()) {
|
|
21675
|
+
const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
|
|
21676
|
+
if (matched.length) out.set(memory.memory_id, new Set(matched));
|
|
21677
|
+
}
|
|
21678
|
+
return out;
|
|
21679
|
+
};
|
|
21680
|
+
const topicGraphRanking = async (query, recallOptions = {}) => {
|
|
21681
|
+
const wanted = new Set(extractQueryEntities(query).map(normalizeEntityName).filter(Boolean));
|
|
21682
|
+
if (wanted.size === 0 || recallOptions.memoryIds?.length === 0) return [];
|
|
21683
|
+
const rows = await pages(
|
|
21684
|
+
metadata2,
|
|
21685
|
+
{
|
|
21686
|
+
topics: [...wanted].slice(0, MAX_QUERY_TOPICS),
|
|
21687
|
+
...recallOptions.scopes && { scopes: recallOptions.scopes },
|
|
21688
|
+
...recallOptions.factTypes && { fact_types: recallOptions.factTypes },
|
|
21689
|
+
...recallOptions.memoryIds && { memory_ids: recallOptions.memoryIds }
|
|
21690
|
+
},
|
|
21691
|
+
GRAPH_LANE_ROWS
|
|
21692
|
+
);
|
|
21693
|
+
return rows.map(({ memory }) => ({
|
|
21694
|
+
memoryId: memory.memory_id,
|
|
21695
|
+
matched: [...canonicalTopics(memory)].filter((name) => wanted.has(name)).length
|
|
21696
|
+
})).filter((row) => row.matched > 0).sort((a, b) => b.matched - a.matched).slice(0, NODE_BUDGET).map((row) => row.memoryId);
|
|
21697
|
+
};
|
|
21486
21698
|
const enumerateIds = async (read, ids, filters) => (await Promise.all(
|
|
21487
21699
|
chunks2([...new Set(ids)], MAX_QUERY_IDS).map(
|
|
21488
21700
|
(memory_ids) => pages(read, { ...filters, memory_ids })
|
|
@@ -21708,7 +21920,8 @@ function createRemoteMemoryStore(options) {
|
|
|
21708
21920
|
};
|
|
21709
21921
|
},
|
|
21710
21922
|
extractTopics: async (memoryIds, extractOptions) => {
|
|
21711
|
-
const
|
|
21923
|
+
const start = Date.now();
|
|
21924
|
+
const extractedAt = extractOptions.now ?? start;
|
|
21712
21925
|
const skippedIds = [];
|
|
21713
21926
|
const skippedReasons = /* @__PURE__ */ new Map();
|
|
21714
21927
|
const skip = (id, reason) => {
|
|
@@ -21726,7 +21939,18 @@ function createRemoteMemoryStore(options) {
|
|
|
21726
21939
|
else if (memory.is_deleted || memory.topics_user_managed) skip(id, "excluded");
|
|
21727
21940
|
else inputs.push({ id, content: memory.content });
|
|
21728
21941
|
}
|
|
21729
|
-
const
|
|
21942
|
+
const batches = [];
|
|
21943
|
+
const llmFailures = /* @__PURE__ */ new Map();
|
|
21944
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, {
|
|
21945
|
+
...extractOptions,
|
|
21946
|
+
onBatch: (batch) => {
|
|
21947
|
+
batches.push(batch);
|
|
21948
|
+
if (batch.failure) {
|
|
21949
|
+
for (const id of batch.memoryIds) llmFailures.set(id, batch.failure);
|
|
21950
|
+
}
|
|
21951
|
+
notifyMemoryCallback(extractOptions.onBatch, batch);
|
|
21952
|
+
}
|
|
21953
|
+
});
|
|
21730
21954
|
const answered = /* @__PURE__ */ new Map();
|
|
21731
21955
|
for (const input of inputs) {
|
|
21732
21956
|
const entities = entitiesByMemory.get(input.id);
|
|
@@ -21775,7 +21999,16 @@ function createRemoteMemoryStore(options) {
|
|
|
21775
21999
|
getLogger().warn("[memory/remote-store] Failed to write extracted topics:", error);
|
|
21776
22000
|
for (const id of answered.keys()) fail(id, "link-failed");
|
|
21777
22001
|
}
|
|
21778
|
-
return {
|
|
22002
|
+
return {
|
|
22003
|
+
entitiesByMemory,
|
|
22004
|
+
stampedIds,
|
|
22005
|
+
skippedIds,
|
|
22006
|
+
skippedReasons,
|
|
22007
|
+
batchCount: batches.length,
|
|
22008
|
+
durationMs: Date.now() - start,
|
|
22009
|
+
batches,
|
|
22010
|
+
llmFailures
|
|
22011
|
+
};
|
|
21779
22012
|
},
|
|
21780
22013
|
stampTopicsExtracted: async (memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) => {
|
|
21781
22014
|
const ids = [...new Set(memoryIds)];
|
|
@@ -21902,18 +22135,7 @@ function createRemoteMemoryStore(options) {
|
|
|
21902
22135
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
21903
22136
|
(record2) => stored(record2.memory)
|
|
21904
22137
|
),
|
|
21905
|
-
memoriesByTopics
|
|
21906
|
-
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
21907
|
-
const out = /* @__PURE__ */ new Map();
|
|
21908
|
-
const pages2 = await Promise.all(
|
|
21909
|
-
chunks2([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
21910
|
-
);
|
|
21911
|
-
for (const { memory } of pages2.flat()) {
|
|
21912
|
-
const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
|
|
21913
|
-
if (matched.length) out.set(memory.memory_id, new Set(matched));
|
|
21914
|
-
}
|
|
21915
|
-
return out;
|
|
21916
|
-
},
|
|
22138
|
+
memoriesByTopics,
|
|
21917
22139
|
topicsByMemories: async (memoryIds) => {
|
|
21918
22140
|
const out = /* @__PURE__ */ new Map();
|
|
21919
22141
|
for (const { memory } of await enumerateIds(decrypted, memoryIds, {
|
|
@@ -23791,9 +24013,13 @@ function formatVaultHits(hits) {
|
|
|
23791
24013
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
23792
24014
|
${h.content}`).join("\n\n");
|
|
23793
24015
|
}
|
|
23794
|
-
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
24016
|
+
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions, callbacks) {
|
|
23795
24017
|
const limit = searchOptions?.limit ?? 5;
|
|
23796
24018
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
24019
|
+
const recallEmbeddingOptions = {
|
|
24020
|
+
...embeddingOptions,
|
|
24021
|
+
taskType: "memory_recall_embed"
|
|
24022
|
+
};
|
|
23797
24023
|
const tuningForward = {
|
|
23798
24024
|
...searchOptions?.rerankTopN !== void 0 && { rerankTopN: searchOptions.rerankTopN },
|
|
23799
24025
|
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
@@ -23847,6 +24073,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23847
24073
|
const requestLimit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.floor(rawLimit), 1), RECALL_MAX_LIMIT) : limit;
|
|
23848
24074
|
const argFolderId = args.folder_id;
|
|
23849
24075
|
if (!query || typeof query !== "string") {
|
|
24076
|
+
notifyMemoryCallback(callbacks?.onError, new Error("A search query is required."));
|
|
23850
24077
|
return "Error: A search query is required.";
|
|
23851
24078
|
}
|
|
23852
24079
|
try {
|
|
@@ -23854,7 +24081,11 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23854
24081
|
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
23855
24082
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
23856
24083
|
if (searchOptions?.useFusion === false) {
|
|
24084
|
+
let candidateCount;
|
|
23857
24085
|
const legacyOptions = {
|
|
24086
|
+
onCandidateCount: (count2) => {
|
|
24087
|
+
candidateCount = count2;
|
|
24088
|
+
},
|
|
23858
24089
|
limit: requestLimit,
|
|
23859
24090
|
minSimilarity,
|
|
23860
24091
|
useFusion: false,
|
|
@@ -23862,13 +24093,38 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23862
24093
|
...folderId !== void 0 && { folderId },
|
|
23863
24094
|
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
23864
24095
|
};
|
|
23865
|
-
const
|
|
24096
|
+
const start = Date.now();
|
|
24097
|
+
const outcome2 = "retain" in vaultCtx ? await vaultCtx.factSource.search(query, legacyOptions) : await searchVaultMemoriesWithSize(
|
|
23866
24098
|
query,
|
|
23867
24099
|
vaultCtx,
|
|
23868
|
-
|
|
24100
|
+
recallEmbeddingOptions,
|
|
23869
24101
|
cache,
|
|
23870
24102
|
legacyOptions
|
|
23871
24103
|
);
|
|
24104
|
+
const { results: legacy, embeddingsUnavailable, vaultSize } = outcome2;
|
|
24105
|
+
const diagnostics = factRecallDiagnostics(
|
|
24106
|
+
legacy.map((m) => m.similarity),
|
|
24107
|
+
Date.now() - start,
|
|
24108
|
+
{
|
|
24109
|
+
vaultSize,
|
|
24110
|
+
minScore: minSimilarity,
|
|
24111
|
+
embeddingsUnavailable,
|
|
24112
|
+
candidateCount,
|
|
24113
|
+
truncated: candidateCount !== void 0 && candidateCount > requestLimit,
|
|
24114
|
+
decryptLast: outcome2.decryptLast,
|
|
24115
|
+
vaultRowsDecrypted: outcome2.rowsDecrypted,
|
|
24116
|
+
vaultRowsEmbedded: outcome2.rowsEmbedded,
|
|
24117
|
+
queryEmbedMs: outcome2.queryEmbedMs
|
|
24118
|
+
}
|
|
24119
|
+
);
|
|
24120
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, diagnostics);
|
|
24121
|
+
if (diagnostics.truncated) {
|
|
24122
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
24123
|
+
requestedLimit: requestLimit,
|
|
24124
|
+
effectiveLimit: requestLimit,
|
|
24125
|
+
truncatedByBudget: false
|
|
24126
|
+
});
|
|
24127
|
+
}
|
|
23872
24128
|
if (legacy.length === 0) {
|
|
23873
24129
|
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
23874
24130
|
}
|
|
@@ -23890,6 +24146,14 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23890
24146
|
{
|
|
23891
24147
|
onDiagnostics: (d) => {
|
|
23892
24148
|
recallDegraded = d.degraded;
|
|
24149
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, d);
|
|
24150
|
+
if (d.truncated) {
|
|
24151
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
24152
|
+
requestedLimit: requestLimit,
|
|
24153
|
+
effectiveLimit: requestLimit,
|
|
24154
|
+
truncatedByBudget: false
|
|
24155
|
+
});
|
|
24156
|
+
}
|
|
23893
24157
|
},
|
|
23894
24158
|
types: ["fact"],
|
|
23895
24159
|
limit: requestLimit,
|
|
@@ -23922,6 +24186,10 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23922
24186
|
|
|
23923
24187
|
${formatted}`;
|
|
23924
24188
|
} catch (error) {
|
|
24189
|
+
notifyMemoryCallback(
|
|
24190
|
+
callbacks?.onError,
|
|
24191
|
+
error instanceof Error ? error : new Error(String(error))
|
|
24192
|
+
);
|
|
23925
24193
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
23926
24194
|
return `Error searching vault: ${message}`;
|
|
23927
24195
|
}
|
|
@@ -25397,6 +25665,15 @@ function useChat(options) {
|
|
|
25397
25665
|
detachControllerRef.current = null;
|
|
25398
25666
|
pendingResumeRef.current = null;
|
|
25399
25667
|
}, [resumable, fireCancel]);
|
|
25668
|
+
const cancel = (0, import_react4.useCallback)(
|
|
25669
|
+
(handle) => {
|
|
25670
|
+
if (resumable) fireCancel(handle);
|
|
25671
|
+
if (pendingResumeRef.current?.inferenceId === handle.inferenceId) {
|
|
25672
|
+
pendingResumeRef.current = null;
|
|
25673
|
+
}
|
|
25674
|
+
},
|
|
25675
|
+
[resumable, fireCancel]
|
|
25676
|
+
);
|
|
25400
25677
|
const detach = (0, import_react4.useCallback)(() => {
|
|
25401
25678
|
if (detachControllerRef.current) {
|
|
25402
25679
|
detachControllerRef.current.abort();
|
|
@@ -25655,6 +25932,7 @@ function useChat(options) {
|
|
|
25655
25932
|
isLoading,
|
|
25656
25933
|
sendMessage,
|
|
25657
25934
|
stop,
|
|
25935
|
+
cancel,
|
|
25658
25936
|
detach,
|
|
25659
25937
|
resumeStream: resumeStream2
|
|
25660
25938
|
};
|
|
@@ -27064,6 +27342,7 @@ function useChatStorage(options) {
|
|
|
27064
27342
|
isLoading,
|
|
27065
27343
|
sendMessage: baseSendMessage,
|
|
27066
27344
|
stop: baseStop,
|
|
27345
|
+
cancel: baseCancel,
|
|
27067
27346
|
detach,
|
|
27068
27347
|
resumeStream: baseResumeStream
|
|
27069
27348
|
} = useChat({
|
|
@@ -27087,6 +27366,9 @@ function useChatStorage(options) {
|
|
|
27087
27366
|
});
|
|
27088
27367
|
const pendingResumeRef = (0, import_react5.useRef)(null);
|
|
27089
27368
|
const isResumingRef = (0, import_react5.useRef)(false);
|
|
27369
|
+
const activeResumeRef = (0, import_react5.useRef)(null);
|
|
27370
|
+
const retirementRef = (0, import_react5.useRef)(null);
|
|
27371
|
+
const retirementStopRequestedRef = (0, import_react5.useRef)(false);
|
|
27090
27372
|
const createConversation = (0, import_react5.useCallback)(
|
|
27091
27373
|
async (opts) => {
|
|
27092
27374
|
const { result, queued } = await writeOrQueue(
|
|
@@ -27286,6 +27568,143 @@ function useChatStorage(options) {
|
|
|
27286
27568
|
activeToolSetsRef.current = activeToolSets;
|
|
27287
27569
|
const getTokenRef = (0, import_react5.useRef)(getToken);
|
|
27288
27570
|
getTokenRef.current = getToken;
|
|
27571
|
+
const finalizeResumedRow = (0, import_react5.useCallback)(
|
|
27572
|
+
async (ctx, data, wasStopped, responseDuration, viaQueue = false) => {
|
|
27573
|
+
const { content, thinking } = extractAssistantText(data);
|
|
27574
|
+
let parentMessageId = ctx.userMessageUniqueId;
|
|
27575
|
+
let knownIds = ctx.knownToolCallEventIds;
|
|
27576
|
+
if (ctx.convId && (!knownIds || !parentMessageId)) {
|
|
27577
|
+
let storedMessages = null;
|
|
27578
|
+
try {
|
|
27579
|
+
storedMessages = await getMessages(ctx.convId);
|
|
27580
|
+
} catch {
|
|
27581
|
+
}
|
|
27582
|
+
if (storedMessages) {
|
|
27583
|
+
if (!knownIds) {
|
|
27584
|
+
knownIds = /* @__PURE__ */ new Set();
|
|
27585
|
+
for (const msg of storedMessages) {
|
|
27586
|
+
if (msg.uniqueId === ctx.assistantUniqueId) continue;
|
|
27587
|
+
if (msg.toolCallEvents) {
|
|
27588
|
+
for (const evt of msg.toolCallEvents) {
|
|
27589
|
+
if (evt.id) knownIds.add(evt.id);
|
|
27590
|
+
}
|
|
27591
|
+
}
|
|
27592
|
+
}
|
|
27593
|
+
}
|
|
27594
|
+
if (!parentMessageId) {
|
|
27595
|
+
for (let i = storedMessages.length - 1; i >= 0; i--) {
|
|
27596
|
+
if (storedMessages[i].uniqueId !== ctx.assistantUniqueId) {
|
|
27597
|
+
parentMessageId = storedMessages[i].uniqueId;
|
|
27598
|
+
break;
|
|
27599
|
+
}
|
|
27600
|
+
}
|
|
27601
|
+
}
|
|
27602
|
+
}
|
|
27603
|
+
}
|
|
27604
|
+
const allToolCallEvents = getToolCallEvents(data);
|
|
27605
|
+
const currentTurnToolCallEvents = knownIds ? allToolCallEvents?.filter(
|
|
27606
|
+
(evt) => evt.id !== void 0 && evt.id !== null && !knownIds.has(evt.id)
|
|
27607
|
+
) : allToolCallEvents;
|
|
27608
|
+
const baseSources = ctx.sources ?? [];
|
|
27609
|
+
const seenSourceUrls = new Set(
|
|
27610
|
+
baseSources.map((s) => s.url).filter((url) => !!url)
|
|
27611
|
+
);
|
|
27612
|
+
const toolEventSources = extractSourcesFromToolCallEvents(currentTurnToolCallEvents);
|
|
27613
|
+
const sources = [
|
|
27614
|
+
...baseSources,
|
|
27615
|
+
...toolEventSources.filter((s) => !s.url || !seenSourceUrls.has(s.url))
|
|
27616
|
+
].filter((source) => !source.url?.includes(MCP_R2_DOMAIN));
|
|
27617
|
+
const rowOpts = {
|
|
27618
|
+
conversationId: ctx.convId,
|
|
27619
|
+
role: "assistant",
|
|
27620
|
+
content,
|
|
27621
|
+
model: data.model || ctx.model || "",
|
|
27622
|
+
imageModel: ctx.imageModel || getImageModel(data),
|
|
27623
|
+
usage: convertUsageToStored(data),
|
|
27624
|
+
responseDuration,
|
|
27625
|
+
sources,
|
|
27626
|
+
thoughtProcess: finalizeThoughtProcess(ctx.thoughtProcess),
|
|
27627
|
+
thinking,
|
|
27628
|
+
wasStopped,
|
|
27629
|
+
parentMessageId,
|
|
27630
|
+
toolCallEvents: currentTurnToolCallEvents && currentTurnToolCallEvents.length > 0 ? currentTurnToolCallEvents : void 0,
|
|
27631
|
+
uniqueId: ctx.assistantUniqueId
|
|
27632
|
+
};
|
|
27633
|
+
if (!viaQueue) return upsertMessageOp(storageCtx, rowOpts);
|
|
27634
|
+
const { result } = await writeOrQueue(
|
|
27635
|
+
"createMessage",
|
|
27636
|
+
rowOpts,
|
|
27637
|
+
() => upsertMessageOp(storageCtx, rowOpts),
|
|
27638
|
+
() => makeSyntheticStoredMessage(rowOpts),
|
|
27639
|
+
ctx.userMessageQueueId ? [ctx.userMessageQueueId] : []
|
|
27640
|
+
);
|
|
27641
|
+
return result;
|
|
27642
|
+
},
|
|
27643
|
+
[storageCtx, getMessages, writeOrQueue]
|
|
27644
|
+
);
|
|
27645
|
+
const retirePendingTurn = (0, import_react5.useCallback)(async () => {
|
|
27646
|
+
const visible = activeResumeRef.current;
|
|
27647
|
+
if (visible && !visible.headless) {
|
|
27648
|
+
baseStop();
|
|
27649
|
+
await visible.settled;
|
|
27650
|
+
}
|
|
27651
|
+
if (retirementRef.current) return retirementRef.current;
|
|
27652
|
+
const active = activeResumeRef.current;
|
|
27653
|
+
if (active && !active.headless) return "Resume already in progress";
|
|
27654
|
+
const pending = pendingResumeRef.current;
|
|
27655
|
+
if (!pending) return null;
|
|
27656
|
+
if (!pending.userMessageUniqueId) {
|
|
27657
|
+
if (active?.context === pending) return null;
|
|
27658
|
+
if (!pending.partialData) {
|
|
27659
|
+
pendingResumeRef.current = null;
|
|
27660
|
+
return null;
|
|
27661
|
+
}
|
|
27662
|
+
}
|
|
27663
|
+
if (active?.context === pending) return "Resume already in progress";
|
|
27664
|
+
pendingResumeRef.current = null;
|
|
27665
|
+
retirementStopRequestedRef.current = false;
|
|
27666
|
+
const retirement = Promise.resolve().then(async () => {
|
|
27667
|
+
try {
|
|
27668
|
+
const data = pending.partialData;
|
|
27669
|
+
if (data && pending.assistantUniqueId) {
|
|
27670
|
+
const { content, thinking } = extractAssistantText(data);
|
|
27671
|
+
if (content || thinking || (getToolCallEvents(data)?.length ?? 0) > 0) {
|
|
27672
|
+
if (walletAddress && signMessage && !hasEncryptionKey(walletAddress)) {
|
|
27673
|
+
try {
|
|
27674
|
+
await requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner);
|
|
27675
|
+
} catch {
|
|
27676
|
+
}
|
|
27677
|
+
}
|
|
27678
|
+
await finalizeResumedRow(
|
|
27679
|
+
pending,
|
|
27680
|
+
data,
|
|
27681
|
+
true,
|
|
27682
|
+
(Date.now() - pending.startTime) / 1e3,
|
|
27683
|
+
true
|
|
27684
|
+
);
|
|
27685
|
+
}
|
|
27686
|
+
}
|
|
27687
|
+
if (pending.handle) baseCancel(pending.handle);
|
|
27688
|
+
return null;
|
|
27689
|
+
} catch (err) {
|
|
27690
|
+
pendingResumeRef.current = pending;
|
|
27691
|
+
if (retirementStopRequestedRef.current && pending.handle) {
|
|
27692
|
+
baseCancel(pending.handle);
|
|
27693
|
+
pendingResumeRef.current = { ...pending, handle: null };
|
|
27694
|
+
}
|
|
27695
|
+
return err instanceof Error ? err.message : "Failed to store detached message";
|
|
27696
|
+
}
|
|
27697
|
+
});
|
|
27698
|
+
retirementRef.current = retirement;
|
|
27699
|
+
try {
|
|
27700
|
+
return await retirement;
|
|
27701
|
+
} finally {
|
|
27702
|
+
if (retirementRef.current === retirement) {
|
|
27703
|
+
retirementRef.current = null;
|
|
27704
|
+
retirementStopRequestedRef.current = false;
|
|
27705
|
+
}
|
|
27706
|
+
}
|
|
27707
|
+
}, [baseCancel, baseStop, finalizeResumedRow, walletAddress, signMessage, embeddedWalletSigner]);
|
|
27289
27708
|
const sendMessage = (0, import_react5.useCallback)(
|
|
27290
27709
|
async (args) => {
|
|
27291
27710
|
const {
|
|
@@ -27337,7 +27756,11 @@ function useChatStorage(options) {
|
|
|
27337
27756
|
maskForCall: (text14) => redactor ? redactor.maskText(text14) : text14
|
|
27338
27757
|
};
|
|
27339
27758
|
};
|
|
27340
|
-
|
|
27759
|
+
const retirementError = await retirePendingTurn();
|
|
27760
|
+
if (retirementError) {
|
|
27761
|
+
if (!skipStorage) return { data: null, error: retirementError };
|
|
27762
|
+
getLogger().warn("[useChatStorage] detached partial not saved:", retirementError);
|
|
27763
|
+
}
|
|
27341
27764
|
const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${(0, import_uuid7.v7)()}` : void 0);
|
|
27342
27765
|
const embedToolText = (text14, mask, masked, token) => {
|
|
27343
27766
|
const opts = {
|
|
@@ -27861,6 +28284,7 @@ function useChatStorage(options) {
|
|
|
27861
28284
|
handle: detachedResult.resume ?? null,
|
|
27862
28285
|
convId,
|
|
27863
28286
|
userMessageUniqueId: storedUserMessage.uniqueId,
|
|
28287
|
+
userMessageQueueId: userMsgQueueId,
|
|
27864
28288
|
assistantUniqueId: rowId,
|
|
27865
28289
|
model,
|
|
27866
28290
|
imageModel,
|
|
@@ -28087,6 +28511,7 @@ function useChatStorage(options) {
|
|
|
28087
28511
|
getMessages,
|
|
28088
28512
|
storageCtx,
|
|
28089
28513
|
baseSendMessage,
|
|
28514
|
+
retirePendingTurn,
|
|
28090
28515
|
embedMessageAsync,
|
|
28091
28516
|
minContentLength,
|
|
28092
28517
|
walletAddress,
|
|
@@ -28101,72 +28526,9 @@ function useChatStorage(options) {
|
|
|
28101
28526
|
onPiiRedacted
|
|
28102
28527
|
]
|
|
28103
28528
|
);
|
|
28104
|
-
const finalizeResumedRow = (0, import_react5.useCallback)(
|
|
28105
|
-
async (ctx, data, wasStopped, responseDuration) => {
|
|
28106
|
-
const { content, thinking } = extractAssistantText(data);
|
|
28107
|
-
let parentMessageId = ctx.userMessageUniqueId;
|
|
28108
|
-
let knownIds = ctx.knownToolCallEventIds;
|
|
28109
|
-
if (ctx.convId && (!knownIds || !parentMessageId)) {
|
|
28110
|
-
let storedMessages = null;
|
|
28111
|
-
try {
|
|
28112
|
-
storedMessages = await getMessages(ctx.convId);
|
|
28113
|
-
} catch {
|
|
28114
|
-
}
|
|
28115
|
-
if (storedMessages) {
|
|
28116
|
-
if (!knownIds) {
|
|
28117
|
-
knownIds = /* @__PURE__ */ new Set();
|
|
28118
|
-
for (const msg of storedMessages) {
|
|
28119
|
-
if (msg.toolCallEvents) {
|
|
28120
|
-
for (const evt of msg.toolCallEvents) {
|
|
28121
|
-
if (evt.id) knownIds.add(evt.id);
|
|
28122
|
-
}
|
|
28123
|
-
}
|
|
28124
|
-
}
|
|
28125
|
-
}
|
|
28126
|
-
if (!parentMessageId) {
|
|
28127
|
-
for (let i = storedMessages.length - 1; i >= 0; i--) {
|
|
28128
|
-
if (storedMessages[i].uniqueId !== ctx.assistantUniqueId) {
|
|
28129
|
-
parentMessageId = storedMessages[i].uniqueId;
|
|
28130
|
-
break;
|
|
28131
|
-
}
|
|
28132
|
-
}
|
|
28133
|
-
}
|
|
28134
|
-
}
|
|
28135
|
-
}
|
|
28136
|
-
const allToolCallEvents = getToolCallEvents(data);
|
|
28137
|
-
const currentTurnToolCallEvents = knownIds ? allToolCallEvents?.filter(
|
|
28138
|
-
(evt) => evt.id !== void 0 && evt.id !== null && !knownIds.has(evt.id)
|
|
28139
|
-
) : allToolCallEvents;
|
|
28140
|
-
const baseSources = ctx.sources ?? [];
|
|
28141
|
-
const seenSourceUrls = new Set(
|
|
28142
|
-
baseSources.map((s) => s.url).filter((url) => !!url)
|
|
28143
|
-
);
|
|
28144
|
-
const toolEventSources = extractSourcesFromToolCallEvents(currentTurnToolCallEvents);
|
|
28145
|
-
const sources = [
|
|
28146
|
-
...baseSources,
|
|
28147
|
-
...toolEventSources.filter((s) => !s.url || !seenSourceUrls.has(s.url))
|
|
28148
|
-
].filter((source) => !source.url?.includes(MCP_R2_DOMAIN));
|
|
28149
|
-
return upsertMessageOp(storageCtx, {
|
|
28150
|
-
conversationId: ctx.convId,
|
|
28151
|
-
role: "assistant",
|
|
28152
|
-
content,
|
|
28153
|
-
model: data.model || ctx.model || "",
|
|
28154
|
-
imageModel: ctx.imageModel || getImageModel(data),
|
|
28155
|
-
usage: convertUsageToStored(data),
|
|
28156
|
-
responseDuration,
|
|
28157
|
-
sources,
|
|
28158
|
-
thoughtProcess: finalizeThoughtProcess(ctx.thoughtProcess),
|
|
28159
|
-
thinking,
|
|
28160
|
-
wasStopped,
|
|
28161
|
-
parentMessageId,
|
|
28162
|
-
uniqueId: ctx.assistantUniqueId
|
|
28163
|
-
});
|
|
28164
|
-
},
|
|
28165
|
-
[storageCtx, getMessages]
|
|
28166
|
-
);
|
|
28167
28529
|
const resumeStream2 = (0, import_react5.useCallback)(
|
|
28168
28530
|
async (handleOverride, opts) => {
|
|
28169
|
-
if (isResumingRef.current) {
|
|
28531
|
+
if (isResumingRef.current || retirementRef.current) {
|
|
28170
28532
|
return { data: null, error: "Resume already in progress", assistantMessage: null };
|
|
28171
28533
|
}
|
|
28172
28534
|
const pending = pendingResumeRef.current;
|
|
@@ -28195,6 +28557,7 @@ function useChatStorage(options) {
|
|
|
28195
28557
|
if (pendingResumeRef.current === rctx) pendingResumeRef.current = null;
|
|
28196
28558
|
};
|
|
28197
28559
|
const safeFinalize = async (data, wasStopped, responseDuration) => {
|
|
28560
|
+
rctx.partialData = data;
|
|
28198
28561
|
try {
|
|
28199
28562
|
return { message: await finalizeResumedRow(rctx, data, wasStopped, responseDuration) };
|
|
28200
28563
|
} catch (writeErr) {
|
|
@@ -28204,6 +28567,13 @@ function useChatStorage(options) {
|
|
|
28204
28567
|
}
|
|
28205
28568
|
};
|
|
28206
28569
|
isResumingRef.current = true;
|
|
28570
|
+
let markSettled = () => {
|
|
28571
|
+
};
|
|
28572
|
+
const settled = new Promise((resolve) => {
|
|
28573
|
+
markSettled = resolve;
|
|
28574
|
+
});
|
|
28575
|
+
const activeResume = { context: rctx, headless: opts?.headless === true, settled };
|
|
28576
|
+
activeResumeRef.current = activeResume;
|
|
28207
28577
|
try {
|
|
28208
28578
|
const result = await baseResumeStream(handle, { headless: opts?.headless });
|
|
28209
28579
|
const responseDuration = (Date.now() - rctx.startTime) / 1e3;
|
|
@@ -28280,11 +28650,17 @@ function useChatStorage(options) {
|
|
|
28280
28650
|
throw err;
|
|
28281
28651
|
} finally {
|
|
28282
28652
|
isResumingRef.current = false;
|
|
28653
|
+
if (activeResumeRef.current === activeResume) activeResumeRef.current = null;
|
|
28654
|
+
markSettled();
|
|
28283
28655
|
}
|
|
28284
28656
|
},
|
|
28285
28657
|
[baseResumeStream, currentConversationId, finalizeResumedRow, embedMessageAsync]
|
|
28286
28658
|
);
|
|
28287
28659
|
const stop = (0, import_react5.useCallback)(() => {
|
|
28660
|
+
if (retirementRef.current) {
|
|
28661
|
+
retirementStopRequestedRef.current = true;
|
|
28662
|
+
return;
|
|
28663
|
+
}
|
|
28288
28664
|
const pending = pendingResumeRef.current;
|
|
28289
28665
|
if (pending && pending.assistantUniqueId && !isResumingRef.current) {
|
|
28290
28666
|
const finalize = pending;
|