@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.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
|
},
|
|
@@ -21708,7 +21885,8 @@ function createRemoteMemoryStore(options) {
|
|
|
21708
21885
|
};
|
|
21709
21886
|
},
|
|
21710
21887
|
extractTopics: async (memoryIds, extractOptions) => {
|
|
21711
|
-
const
|
|
21888
|
+
const start = Date.now();
|
|
21889
|
+
const extractedAt = extractOptions.now ?? start;
|
|
21712
21890
|
const skippedIds = [];
|
|
21713
21891
|
const skippedReasons = /* @__PURE__ */ new Map();
|
|
21714
21892
|
const skip = (id, reason) => {
|
|
@@ -21726,7 +21904,18 @@ function createRemoteMemoryStore(options) {
|
|
|
21726
21904
|
else if (memory.is_deleted || memory.topics_user_managed) skip(id, "excluded");
|
|
21727
21905
|
else inputs.push({ id, content: memory.content });
|
|
21728
21906
|
}
|
|
21729
|
-
const
|
|
21907
|
+
const batches = [];
|
|
21908
|
+
const llmFailures = /* @__PURE__ */ new Map();
|
|
21909
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, {
|
|
21910
|
+
...extractOptions,
|
|
21911
|
+
onBatch: (batch) => {
|
|
21912
|
+
batches.push(batch);
|
|
21913
|
+
if (batch.failure) {
|
|
21914
|
+
for (const id of batch.memoryIds) llmFailures.set(id, batch.failure);
|
|
21915
|
+
}
|
|
21916
|
+
notifyMemoryCallback(extractOptions.onBatch, batch);
|
|
21917
|
+
}
|
|
21918
|
+
});
|
|
21730
21919
|
const answered = /* @__PURE__ */ new Map();
|
|
21731
21920
|
for (const input of inputs) {
|
|
21732
21921
|
const entities = entitiesByMemory.get(input.id);
|
|
@@ -21775,7 +21964,16 @@ function createRemoteMemoryStore(options) {
|
|
|
21775
21964
|
getLogger().warn("[memory/remote-store] Failed to write extracted topics:", error);
|
|
21776
21965
|
for (const id of answered.keys()) fail(id, "link-failed");
|
|
21777
21966
|
}
|
|
21778
|
-
return {
|
|
21967
|
+
return {
|
|
21968
|
+
entitiesByMemory,
|
|
21969
|
+
stampedIds,
|
|
21970
|
+
skippedIds,
|
|
21971
|
+
skippedReasons,
|
|
21972
|
+
batchCount: batches.length,
|
|
21973
|
+
durationMs: Date.now() - start,
|
|
21974
|
+
batches,
|
|
21975
|
+
llmFailures
|
|
21976
|
+
};
|
|
21779
21977
|
},
|
|
21780
21978
|
stampTopicsExtracted: async (memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) => {
|
|
21781
21979
|
const ids = [...new Set(memoryIds)];
|
|
@@ -23791,9 +23989,13 @@ function formatVaultHits(hits) {
|
|
|
23791
23989
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
23792
23990
|
${h.content}`).join("\n\n");
|
|
23793
23991
|
}
|
|
23794
|
-
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
23992
|
+
function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOptions, callbacks) {
|
|
23795
23993
|
const limit = searchOptions?.limit ?? 5;
|
|
23796
23994
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
23995
|
+
const recallEmbeddingOptions = {
|
|
23996
|
+
...embeddingOptions,
|
|
23997
|
+
taskType: "memory_recall_embed"
|
|
23998
|
+
};
|
|
23797
23999
|
const tuningForward = {
|
|
23798
24000
|
...searchOptions?.rerankTopN !== void 0 && { rerankTopN: searchOptions.rerankTopN },
|
|
23799
24001
|
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
@@ -23847,6 +24049,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23847
24049
|
const requestLimit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.floor(rawLimit), 1), RECALL_MAX_LIMIT) : limit;
|
|
23848
24050
|
const argFolderId = args.folder_id;
|
|
23849
24051
|
if (!query || typeof query !== "string") {
|
|
24052
|
+
notifyMemoryCallback(callbacks?.onError, new Error("A search query is required."));
|
|
23850
24053
|
return "Error: A search query is required.";
|
|
23851
24054
|
}
|
|
23852
24055
|
try {
|
|
@@ -23854,7 +24057,11 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23854
24057
|
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
23855
24058
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
23856
24059
|
if (searchOptions?.useFusion === false) {
|
|
24060
|
+
let candidateCount;
|
|
23857
24061
|
const legacyOptions = {
|
|
24062
|
+
onCandidateCount: (count2) => {
|
|
24063
|
+
candidateCount = count2;
|
|
24064
|
+
},
|
|
23858
24065
|
limit: requestLimit,
|
|
23859
24066
|
minSimilarity,
|
|
23860
24067
|
useFusion: false,
|
|
@@ -23862,13 +24069,38 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23862
24069
|
...folderId !== void 0 && { folderId },
|
|
23863
24070
|
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
23864
24071
|
};
|
|
23865
|
-
const
|
|
24072
|
+
const start = Date.now();
|
|
24073
|
+
const outcome2 = "retain" in vaultCtx ? await vaultCtx.factSource.search(query, legacyOptions) : await searchVaultMemoriesWithSize(
|
|
23866
24074
|
query,
|
|
23867
24075
|
vaultCtx,
|
|
23868
|
-
|
|
24076
|
+
recallEmbeddingOptions,
|
|
23869
24077
|
cache,
|
|
23870
24078
|
legacyOptions
|
|
23871
24079
|
);
|
|
24080
|
+
const { results: legacy, embeddingsUnavailable, vaultSize } = outcome2;
|
|
24081
|
+
const diagnostics = factRecallDiagnostics(
|
|
24082
|
+
legacy.map((m) => m.similarity),
|
|
24083
|
+
Date.now() - start,
|
|
24084
|
+
{
|
|
24085
|
+
vaultSize,
|
|
24086
|
+
minScore: minSimilarity,
|
|
24087
|
+
embeddingsUnavailable,
|
|
24088
|
+
candidateCount,
|
|
24089
|
+
truncated: candidateCount !== void 0 && candidateCount > requestLimit,
|
|
24090
|
+
decryptLast: outcome2.decryptLast,
|
|
24091
|
+
vaultRowsDecrypted: outcome2.rowsDecrypted,
|
|
24092
|
+
vaultRowsEmbedded: outcome2.rowsEmbedded,
|
|
24093
|
+
queryEmbedMs: outcome2.queryEmbedMs
|
|
24094
|
+
}
|
|
24095
|
+
);
|
|
24096
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, diagnostics);
|
|
24097
|
+
if (diagnostics.truncated) {
|
|
24098
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
24099
|
+
requestedLimit: requestLimit,
|
|
24100
|
+
effectiveLimit: requestLimit,
|
|
24101
|
+
truncatedByBudget: false
|
|
24102
|
+
});
|
|
24103
|
+
}
|
|
23872
24104
|
if (legacy.length === 0) {
|
|
23873
24105
|
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
23874
24106
|
}
|
|
@@ -23890,6 +24122,14 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23890
24122
|
{
|
|
23891
24123
|
onDiagnostics: (d) => {
|
|
23892
24124
|
recallDegraded = d.degraded;
|
|
24125
|
+
notifyMemoryCallback(callbacks?.onDiagnostics, d);
|
|
24126
|
+
if (d.truncated) {
|
|
24127
|
+
notifyMemoryCallback(callbacks?.onTruncated, {
|
|
24128
|
+
requestedLimit: requestLimit,
|
|
24129
|
+
effectiveLimit: requestLimit,
|
|
24130
|
+
truncatedByBudget: false
|
|
24131
|
+
});
|
|
24132
|
+
}
|
|
23893
24133
|
},
|
|
23894
24134
|
types: ["fact"],
|
|
23895
24135
|
limit: requestLimit,
|
|
@@ -23922,6 +24162,10 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
23922
24162
|
|
|
23923
24163
|
${formatted}`;
|
|
23924
24164
|
} catch (error) {
|
|
24165
|
+
notifyMemoryCallback(
|
|
24166
|
+
callbacks?.onError,
|
|
24167
|
+
error instanceof Error ? error : new Error(String(error))
|
|
24168
|
+
);
|
|
23925
24169
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
23926
24170
|
return `Error searching vault: ${message}`;
|
|
23927
24171
|
}
|
|
@@ -25397,6 +25641,15 @@ function useChat(options) {
|
|
|
25397
25641
|
detachControllerRef.current = null;
|
|
25398
25642
|
pendingResumeRef.current = null;
|
|
25399
25643
|
}, [resumable, fireCancel]);
|
|
25644
|
+
const cancel = (0, import_react4.useCallback)(
|
|
25645
|
+
(handle) => {
|
|
25646
|
+
if (resumable) fireCancel(handle);
|
|
25647
|
+
if (pendingResumeRef.current?.inferenceId === handle.inferenceId) {
|
|
25648
|
+
pendingResumeRef.current = null;
|
|
25649
|
+
}
|
|
25650
|
+
},
|
|
25651
|
+
[resumable, fireCancel]
|
|
25652
|
+
);
|
|
25400
25653
|
const detach = (0, import_react4.useCallback)(() => {
|
|
25401
25654
|
if (detachControllerRef.current) {
|
|
25402
25655
|
detachControllerRef.current.abort();
|
|
@@ -25655,6 +25908,7 @@ function useChat(options) {
|
|
|
25655
25908
|
isLoading,
|
|
25656
25909
|
sendMessage,
|
|
25657
25910
|
stop,
|
|
25911
|
+
cancel,
|
|
25658
25912
|
detach,
|
|
25659
25913
|
resumeStream: resumeStream2
|
|
25660
25914
|
};
|
|
@@ -27064,6 +27318,7 @@ function useChatStorage(options) {
|
|
|
27064
27318
|
isLoading,
|
|
27065
27319
|
sendMessage: baseSendMessage,
|
|
27066
27320
|
stop: baseStop,
|
|
27321
|
+
cancel: baseCancel,
|
|
27067
27322
|
detach,
|
|
27068
27323
|
resumeStream: baseResumeStream
|
|
27069
27324
|
} = useChat({
|
|
@@ -27087,6 +27342,9 @@ function useChatStorage(options) {
|
|
|
27087
27342
|
});
|
|
27088
27343
|
const pendingResumeRef = (0, import_react5.useRef)(null);
|
|
27089
27344
|
const isResumingRef = (0, import_react5.useRef)(false);
|
|
27345
|
+
const activeResumeRef = (0, import_react5.useRef)(null);
|
|
27346
|
+
const retirementRef = (0, import_react5.useRef)(null);
|
|
27347
|
+
const retirementStopRequestedRef = (0, import_react5.useRef)(false);
|
|
27090
27348
|
const createConversation = (0, import_react5.useCallback)(
|
|
27091
27349
|
async (opts) => {
|
|
27092
27350
|
const { result, queued } = await writeOrQueue(
|
|
@@ -27286,6 +27544,143 @@ function useChatStorage(options) {
|
|
|
27286
27544
|
activeToolSetsRef.current = activeToolSets;
|
|
27287
27545
|
const getTokenRef = (0, import_react5.useRef)(getToken);
|
|
27288
27546
|
getTokenRef.current = getToken;
|
|
27547
|
+
const finalizeResumedRow = (0, import_react5.useCallback)(
|
|
27548
|
+
async (ctx, data, wasStopped, responseDuration, viaQueue = false) => {
|
|
27549
|
+
const { content, thinking } = extractAssistantText(data);
|
|
27550
|
+
let parentMessageId = ctx.userMessageUniqueId;
|
|
27551
|
+
let knownIds = ctx.knownToolCallEventIds;
|
|
27552
|
+
if (ctx.convId && (!knownIds || !parentMessageId)) {
|
|
27553
|
+
let storedMessages = null;
|
|
27554
|
+
try {
|
|
27555
|
+
storedMessages = await getMessages(ctx.convId);
|
|
27556
|
+
} catch {
|
|
27557
|
+
}
|
|
27558
|
+
if (storedMessages) {
|
|
27559
|
+
if (!knownIds) {
|
|
27560
|
+
knownIds = /* @__PURE__ */ new Set();
|
|
27561
|
+
for (const msg of storedMessages) {
|
|
27562
|
+
if (msg.uniqueId === ctx.assistantUniqueId) continue;
|
|
27563
|
+
if (msg.toolCallEvents) {
|
|
27564
|
+
for (const evt of msg.toolCallEvents) {
|
|
27565
|
+
if (evt.id) knownIds.add(evt.id);
|
|
27566
|
+
}
|
|
27567
|
+
}
|
|
27568
|
+
}
|
|
27569
|
+
}
|
|
27570
|
+
if (!parentMessageId) {
|
|
27571
|
+
for (let i = storedMessages.length - 1; i >= 0; i--) {
|
|
27572
|
+
if (storedMessages[i].uniqueId !== ctx.assistantUniqueId) {
|
|
27573
|
+
parentMessageId = storedMessages[i].uniqueId;
|
|
27574
|
+
break;
|
|
27575
|
+
}
|
|
27576
|
+
}
|
|
27577
|
+
}
|
|
27578
|
+
}
|
|
27579
|
+
}
|
|
27580
|
+
const allToolCallEvents = getToolCallEvents(data);
|
|
27581
|
+
const currentTurnToolCallEvents = knownIds ? allToolCallEvents?.filter(
|
|
27582
|
+
(evt) => evt.id !== void 0 && evt.id !== null && !knownIds.has(evt.id)
|
|
27583
|
+
) : allToolCallEvents;
|
|
27584
|
+
const baseSources = ctx.sources ?? [];
|
|
27585
|
+
const seenSourceUrls = new Set(
|
|
27586
|
+
baseSources.map((s) => s.url).filter((url) => !!url)
|
|
27587
|
+
);
|
|
27588
|
+
const toolEventSources = extractSourcesFromToolCallEvents(currentTurnToolCallEvents);
|
|
27589
|
+
const sources = [
|
|
27590
|
+
...baseSources,
|
|
27591
|
+
...toolEventSources.filter((s) => !s.url || !seenSourceUrls.has(s.url))
|
|
27592
|
+
].filter((source) => !source.url?.includes(MCP_R2_DOMAIN));
|
|
27593
|
+
const rowOpts = {
|
|
27594
|
+
conversationId: ctx.convId,
|
|
27595
|
+
role: "assistant",
|
|
27596
|
+
content,
|
|
27597
|
+
model: data.model || ctx.model || "",
|
|
27598
|
+
imageModel: ctx.imageModel || getImageModel(data),
|
|
27599
|
+
usage: convertUsageToStored(data),
|
|
27600
|
+
responseDuration,
|
|
27601
|
+
sources,
|
|
27602
|
+
thoughtProcess: finalizeThoughtProcess(ctx.thoughtProcess),
|
|
27603
|
+
thinking,
|
|
27604
|
+
wasStopped,
|
|
27605
|
+
parentMessageId,
|
|
27606
|
+
toolCallEvents: currentTurnToolCallEvents && currentTurnToolCallEvents.length > 0 ? currentTurnToolCallEvents : void 0,
|
|
27607
|
+
uniqueId: ctx.assistantUniqueId
|
|
27608
|
+
};
|
|
27609
|
+
if (!viaQueue) return upsertMessageOp(storageCtx, rowOpts);
|
|
27610
|
+
const { result } = await writeOrQueue(
|
|
27611
|
+
"createMessage",
|
|
27612
|
+
rowOpts,
|
|
27613
|
+
() => upsertMessageOp(storageCtx, rowOpts),
|
|
27614
|
+
() => makeSyntheticStoredMessage(rowOpts),
|
|
27615
|
+
ctx.userMessageQueueId ? [ctx.userMessageQueueId] : []
|
|
27616
|
+
);
|
|
27617
|
+
return result;
|
|
27618
|
+
},
|
|
27619
|
+
[storageCtx, getMessages, writeOrQueue]
|
|
27620
|
+
);
|
|
27621
|
+
const retirePendingTurn = (0, import_react5.useCallback)(async () => {
|
|
27622
|
+
const visible = activeResumeRef.current;
|
|
27623
|
+
if (visible && !visible.headless) {
|
|
27624
|
+
baseStop();
|
|
27625
|
+
await visible.settled;
|
|
27626
|
+
}
|
|
27627
|
+
if (retirementRef.current) return retirementRef.current;
|
|
27628
|
+
const active = activeResumeRef.current;
|
|
27629
|
+
if (active && !active.headless) return "Resume already in progress";
|
|
27630
|
+
const pending = pendingResumeRef.current;
|
|
27631
|
+
if (!pending) return null;
|
|
27632
|
+
if (!pending.userMessageUniqueId) {
|
|
27633
|
+
if (active?.context === pending) return null;
|
|
27634
|
+
if (!pending.partialData) {
|
|
27635
|
+
pendingResumeRef.current = null;
|
|
27636
|
+
return null;
|
|
27637
|
+
}
|
|
27638
|
+
}
|
|
27639
|
+
if (active?.context === pending) return "Resume already in progress";
|
|
27640
|
+
pendingResumeRef.current = null;
|
|
27641
|
+
retirementStopRequestedRef.current = false;
|
|
27642
|
+
const retirement = Promise.resolve().then(async () => {
|
|
27643
|
+
try {
|
|
27644
|
+
const data = pending.partialData;
|
|
27645
|
+
if (data && pending.assistantUniqueId) {
|
|
27646
|
+
const { content, thinking } = extractAssistantText(data);
|
|
27647
|
+
if (content || thinking || (getToolCallEvents(data)?.length ?? 0) > 0) {
|
|
27648
|
+
if (walletAddress && signMessage && !hasEncryptionKey(walletAddress)) {
|
|
27649
|
+
try {
|
|
27650
|
+
await requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner);
|
|
27651
|
+
} catch {
|
|
27652
|
+
}
|
|
27653
|
+
}
|
|
27654
|
+
await finalizeResumedRow(
|
|
27655
|
+
pending,
|
|
27656
|
+
data,
|
|
27657
|
+
true,
|
|
27658
|
+
(Date.now() - pending.startTime) / 1e3,
|
|
27659
|
+
true
|
|
27660
|
+
);
|
|
27661
|
+
}
|
|
27662
|
+
}
|
|
27663
|
+
if (pending.handle) baseCancel(pending.handle);
|
|
27664
|
+
return null;
|
|
27665
|
+
} catch (err) {
|
|
27666
|
+
pendingResumeRef.current = pending;
|
|
27667
|
+
if (retirementStopRequestedRef.current && pending.handle) {
|
|
27668
|
+
baseCancel(pending.handle);
|
|
27669
|
+
pendingResumeRef.current = { ...pending, handle: null };
|
|
27670
|
+
}
|
|
27671
|
+
return err instanceof Error ? err.message : "Failed to store detached message";
|
|
27672
|
+
}
|
|
27673
|
+
});
|
|
27674
|
+
retirementRef.current = retirement;
|
|
27675
|
+
try {
|
|
27676
|
+
return await retirement;
|
|
27677
|
+
} finally {
|
|
27678
|
+
if (retirementRef.current === retirement) {
|
|
27679
|
+
retirementRef.current = null;
|
|
27680
|
+
retirementStopRequestedRef.current = false;
|
|
27681
|
+
}
|
|
27682
|
+
}
|
|
27683
|
+
}, [baseCancel, baseStop, finalizeResumedRow, walletAddress, signMessage, embeddedWalletSigner]);
|
|
27289
27684
|
const sendMessage = (0, import_react5.useCallback)(
|
|
27290
27685
|
async (args) => {
|
|
27291
27686
|
const {
|
|
@@ -27337,7 +27732,11 @@ function useChatStorage(options) {
|
|
|
27337
27732
|
maskForCall: (text14) => redactor ? redactor.maskText(text14) : text14
|
|
27338
27733
|
};
|
|
27339
27734
|
};
|
|
27340
|
-
|
|
27735
|
+
const retirementError = await retirePendingTurn();
|
|
27736
|
+
if (retirementError) {
|
|
27737
|
+
if (!skipStorage) return { data: null, error: retirementError };
|
|
27738
|
+
getLogger().warn("[useChatStorage] detached partial not saved:", retirementError);
|
|
27739
|
+
}
|
|
27341
27740
|
const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${(0, import_uuid7.v7)()}` : void 0);
|
|
27342
27741
|
const embedToolText = (text14, mask, masked, token) => {
|
|
27343
27742
|
const opts = {
|
|
@@ -27861,6 +28260,7 @@ function useChatStorage(options) {
|
|
|
27861
28260
|
handle: detachedResult.resume ?? null,
|
|
27862
28261
|
convId,
|
|
27863
28262
|
userMessageUniqueId: storedUserMessage.uniqueId,
|
|
28263
|
+
userMessageQueueId: userMsgQueueId,
|
|
27864
28264
|
assistantUniqueId: rowId,
|
|
27865
28265
|
model,
|
|
27866
28266
|
imageModel,
|
|
@@ -28087,6 +28487,7 @@ function useChatStorage(options) {
|
|
|
28087
28487
|
getMessages,
|
|
28088
28488
|
storageCtx,
|
|
28089
28489
|
baseSendMessage,
|
|
28490
|
+
retirePendingTurn,
|
|
28090
28491
|
embedMessageAsync,
|
|
28091
28492
|
minContentLength,
|
|
28092
28493
|
walletAddress,
|
|
@@ -28101,72 +28502,9 @@ function useChatStorage(options) {
|
|
|
28101
28502
|
onPiiRedacted
|
|
28102
28503
|
]
|
|
28103
28504
|
);
|
|
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
28505
|
const resumeStream2 = (0, import_react5.useCallback)(
|
|
28168
28506
|
async (handleOverride, opts) => {
|
|
28169
|
-
if (isResumingRef.current) {
|
|
28507
|
+
if (isResumingRef.current || retirementRef.current) {
|
|
28170
28508
|
return { data: null, error: "Resume already in progress", assistantMessage: null };
|
|
28171
28509
|
}
|
|
28172
28510
|
const pending = pendingResumeRef.current;
|
|
@@ -28195,6 +28533,7 @@ function useChatStorage(options) {
|
|
|
28195
28533
|
if (pendingResumeRef.current === rctx) pendingResumeRef.current = null;
|
|
28196
28534
|
};
|
|
28197
28535
|
const safeFinalize = async (data, wasStopped, responseDuration) => {
|
|
28536
|
+
rctx.partialData = data;
|
|
28198
28537
|
try {
|
|
28199
28538
|
return { message: await finalizeResumedRow(rctx, data, wasStopped, responseDuration) };
|
|
28200
28539
|
} catch (writeErr) {
|
|
@@ -28204,6 +28543,13 @@ function useChatStorage(options) {
|
|
|
28204
28543
|
}
|
|
28205
28544
|
};
|
|
28206
28545
|
isResumingRef.current = true;
|
|
28546
|
+
let markSettled = () => {
|
|
28547
|
+
};
|
|
28548
|
+
const settled = new Promise((resolve) => {
|
|
28549
|
+
markSettled = resolve;
|
|
28550
|
+
});
|
|
28551
|
+
const activeResume = { context: rctx, headless: opts?.headless === true, settled };
|
|
28552
|
+
activeResumeRef.current = activeResume;
|
|
28207
28553
|
try {
|
|
28208
28554
|
const result = await baseResumeStream(handle, { headless: opts?.headless });
|
|
28209
28555
|
const responseDuration = (Date.now() - rctx.startTime) / 1e3;
|
|
@@ -28280,11 +28626,17 @@ function useChatStorage(options) {
|
|
|
28280
28626
|
throw err;
|
|
28281
28627
|
} finally {
|
|
28282
28628
|
isResumingRef.current = false;
|
|
28629
|
+
if (activeResumeRef.current === activeResume) activeResumeRef.current = null;
|
|
28630
|
+
markSettled();
|
|
28283
28631
|
}
|
|
28284
28632
|
},
|
|
28285
28633
|
[baseResumeStream, currentConversationId, finalizeResumedRow, embedMessageAsync]
|
|
28286
28634
|
);
|
|
28287
28635
|
const stop = (0, import_react5.useCallback)(() => {
|
|
28636
|
+
if (retirementRef.current) {
|
|
28637
|
+
retirementStopRequestedRef.current = true;
|
|
28638
|
+
return;
|
|
28639
|
+
}
|
|
28288
28640
|
const pending = pendingResumeRef.current;
|
|
28289
28641
|
if (pending && pending.assistantUniqueId && !isResumingRef.current) {
|
|
28290
28642
|
const finalize = pending;
|