@anuma/sdk 7.0.0 → 7.0.2
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/index.cjs +421 -111
- package/dist/expo/index.d.mts +25 -24
- package/dist/expo/index.d.ts +25 -24
- package/dist/expo/index.mjs +420 -111
- package/dist/index.cjs +216 -192
- package/dist/index.mjs +216 -192
- package/dist/memory/context.d.mts +8 -0
- package/dist/memory/context.d.ts +8 -0
- package/dist/react/index.cjs +442 -132
- package/dist/react/index.d.mts +30 -44
- package/dist/react/index.d.ts +30 -44
- package/dist/react/index.mjs +441 -132
- package/dist/server/index.cjs +431 -106
- package/dist/server/index.d.mts +30 -21
- package/dist/server/index.d.ts +30 -21
- package/dist/server/index.mjs +430 -106
- package/dist/telemetry/index.d.mts +6 -0
- package/dist/telemetry/index.d.ts +6 -0
- package/dist/tools/selection/index.cjs +28 -10
- package/dist/tools/selection/index.mjs +28 -10
- package/package.json +1 -1
package/dist/server/index.mjs
CHANGED
|
@@ -16019,6 +16019,35 @@ function decodeChunkVector(vector, onMalformed) {
|
|
|
16019
16019
|
}
|
|
16020
16020
|
}
|
|
16021
16021
|
|
|
16022
|
+
// src/lib/scheduling.ts
|
|
16023
|
+
function nowMs() {
|
|
16024
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
16025
|
+
}
|
|
16026
|
+
function yieldToEventLoop() {
|
|
16027
|
+
const scheduler = globalThis.scheduler;
|
|
16028
|
+
if (typeof scheduler?.yield === "function") return scheduler.yield();
|
|
16029
|
+
if (typeof MessageChannel === "function") {
|
|
16030
|
+
return new Promise((resolve) => {
|
|
16031
|
+
const channel = new MessageChannel();
|
|
16032
|
+
channel.port1.onmessage = () => {
|
|
16033
|
+
channel.port1.close();
|
|
16034
|
+
channel.port2.close();
|
|
16035
|
+
resolve();
|
|
16036
|
+
};
|
|
16037
|
+
channel.port2.postMessage(null);
|
|
16038
|
+
});
|
|
16039
|
+
}
|
|
16040
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
16041
|
+
}
|
|
16042
|
+
function createTimeSliceYielder(budgetMs) {
|
|
16043
|
+
let sliceStart = nowMs();
|
|
16044
|
+
return async () => {
|
|
16045
|
+
if (nowMs() - sliceStart < budgetMs) return;
|
|
16046
|
+
await yieldToEventLoop();
|
|
16047
|
+
sliceStart = nowMs();
|
|
16048
|
+
};
|
|
16049
|
+
}
|
|
16050
|
+
|
|
16022
16051
|
// src/lib/db/encryption-utils.ts
|
|
16023
16052
|
var ENCRYPTION_PREFIX = "enc:v3:";
|
|
16024
16053
|
function isEncrypted(value) {
|
|
@@ -16162,6 +16191,12 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
16162
16191
|
const encryptedChunks = msg.chunks ? await encryptJsonField(msg.chunks, address, signMessage, embeddedWalletSigner, true) : void 0;
|
|
16163
16192
|
const encryptedSources = msg.sources ? await encryptJsonField(msg.sources, address, signMessage, embeddedWalletSigner, true) : void 0;
|
|
16164
16193
|
const encryptedThoughtProcess = msg.thoughtProcess ? await encryptJsonField(msg.thoughtProcess, address, signMessage, embeddedWalletSigner, true) : void 0;
|
|
16194
|
+
const encryptedToolCallEvents = Array.isArray(msg.toolCallEvents) ? await encryptToolCallEvents(
|
|
16195
|
+
msg.toolCallEvents,
|
|
16196
|
+
address,
|
|
16197
|
+
signMessage,
|
|
16198
|
+
embeddedWalletSigner
|
|
16199
|
+
) : void 0;
|
|
16165
16200
|
return {
|
|
16166
16201
|
...message,
|
|
16167
16202
|
...encryptedContent !== void 0 && { content: encryptedContent },
|
|
@@ -16169,13 +16204,31 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
16169
16204
|
...encryptedVector !== void 0 && { vector: encryptedVector },
|
|
16170
16205
|
...encryptedChunks !== void 0 && { chunks: encryptedChunks },
|
|
16171
16206
|
...encryptedSources !== void 0 && { sources: encryptedSources },
|
|
16172
|
-
...encryptedThoughtProcess !== void 0 && { thoughtProcess: encryptedThoughtProcess }
|
|
16207
|
+
...encryptedThoughtProcess !== void 0 && { thoughtProcess: encryptedThoughtProcess },
|
|
16208
|
+
...encryptedToolCallEvents !== void 0 && { toolCallEvents: encryptedToolCallEvents }
|
|
16173
16209
|
};
|
|
16174
16210
|
} catch (error) {
|
|
16175
16211
|
getLogger().warn("Failed to encrypt message fields:", error);
|
|
16176
16212
|
throw error;
|
|
16177
16213
|
}
|
|
16178
16214
|
}
|
|
16215
|
+
function mapToolCallPayloads(events, transform) {
|
|
16216
|
+
return Promise.all(
|
|
16217
|
+
events.map(async (event) => {
|
|
16218
|
+
if (!event || typeof event !== "object") return event;
|
|
16219
|
+
const mapped = { ...event };
|
|
16220
|
+
if (typeof event.arguments === "string") mapped.arguments = await transform(event.arguments);
|
|
16221
|
+
if (typeof event.output === "string") mapped.output = await transform(event.output);
|
|
16222
|
+
return mapped;
|
|
16223
|
+
})
|
|
16224
|
+
);
|
|
16225
|
+
}
|
|
16226
|
+
function encryptToolCallEvents(events, address, signMessage, embeddedWalletSigner) {
|
|
16227
|
+
return mapToolCallPayloads(
|
|
16228
|
+
events,
|
|
16229
|
+
(value) => encryptField(value, address, signMessage, embeddedWalletSigner, true)
|
|
16230
|
+
);
|
|
16231
|
+
}
|
|
16179
16232
|
async function decryptMaybeJsonFieldDetailed(value, address) {
|
|
16180
16233
|
if (value === void 0) return { value: void 0, status: "plaintext" };
|
|
16181
16234
|
if (value === null) return { value, status: "plaintext" };
|
|
@@ -16261,6 +16314,10 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
16261
16314
|
message.thoughtProcess,
|
|
16262
16315
|
address
|
|
16263
16316
|
);
|
|
16317
|
+
const toolCallEventsResult = await decryptMaybeJsonFieldDetailed(
|
|
16318
|
+
message.toolCallEvents,
|
|
16319
|
+
address
|
|
16320
|
+
);
|
|
16264
16321
|
let decryptionStatus;
|
|
16265
16322
|
let refreshProbe;
|
|
16266
16323
|
const consider = (status, probe) => {
|
|
@@ -16279,6 +16336,14 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
16279
16336
|
if (thoughtProcessResult.probe) {
|
|
16280
16337
|
consider(thoughtProcessResult.status, thoughtProcessResult.probe);
|
|
16281
16338
|
}
|
|
16339
|
+
if (toolCallEventsResult.probe) {
|
|
16340
|
+
consider(toolCallEventsResult.status, toolCallEventsResult.probe);
|
|
16341
|
+
}
|
|
16342
|
+
const toolCallEvents = Array.isArray(toolCallEventsResult.value) ? await mapToolCallPayloads(toolCallEventsResult.value, async (value) => {
|
|
16343
|
+
const detailed = await decryptFieldDetailed(value, address);
|
|
16344
|
+
consider(detailed.status, isEncrypted(value) ? value : void 0);
|
|
16345
|
+
return detailed.value;
|
|
16346
|
+
}) : void 0;
|
|
16282
16347
|
const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
|
|
16283
16348
|
const result = {
|
|
16284
16349
|
...message,
|
|
@@ -16287,7 +16352,8 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
16287
16352
|
vector: vectorResult.value,
|
|
16288
16353
|
chunks: chunksResult.value,
|
|
16289
16354
|
sources: sourcesResult.value,
|
|
16290
|
-
thoughtProcess: thoughtProcessResult.value
|
|
16355
|
+
thoughtProcess: thoughtProcessResult.value,
|
|
16356
|
+
toolCallEvents
|
|
16291
16357
|
};
|
|
16292
16358
|
if (statusForConsumer) {
|
|
16293
16359
|
result.decryptionStatus = statusForConsumer;
|
|
@@ -16853,7 +16919,7 @@ async function updateMessageChunksOp(ctx, uniqueId, chunks, embeddingModel) {
|
|
|
16853
16919
|
});
|
|
16854
16920
|
return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
16855
16921
|
}
|
|
16856
|
-
var
|
|
16922
|
+
var RAW_REPAIR_PAGE_SIZE = 100;
|
|
16857
16923
|
function chunksWithoutText(raw) {
|
|
16858
16924
|
if (typeof raw !== "string") return null;
|
|
16859
16925
|
let parsed;
|
|
@@ -16876,8 +16942,8 @@ function chunksWithoutText(raw) {
|
|
|
16876
16942
|
async function stripLegacyChunkTextOp(ctx) {
|
|
16877
16943
|
const candidateIds = await ctx.messagesCollection.query(import_watermelondb2.Q.where("chunks", import_watermelondb2.Q.like(`%${import_watermelondb2.Q.sanitizeLikeString('"text":')}%`))).fetchIds();
|
|
16878
16944
|
let stripped = 0;
|
|
16879
|
-
for (let start = 0; start < candidateIds.length; start +=
|
|
16880
|
-
const pageIds = candidateIds.slice(start, start +
|
|
16945
|
+
for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
|
|
16946
|
+
const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
|
|
16881
16947
|
const rows = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).unsafeFetchRaw();
|
|
16882
16948
|
const changedIds = rows.filter((row) => chunksWithoutText(row.chunks) !== null).map((row) => String(row.id));
|
|
16883
16949
|
if (changedIds.length === 0) continue;
|
|
@@ -16901,6 +16967,88 @@ async function stripLegacyChunkTextOp(ctx) {
|
|
|
16901
16967
|
}
|
|
16902
16968
|
return stripped;
|
|
16903
16969
|
}
|
|
16970
|
+
async function encryptedToolCallEventsColumn(raw, address, signMessage, embeddedWalletSigner) {
|
|
16971
|
+
if (typeof raw !== "string") return null;
|
|
16972
|
+
let parsed;
|
|
16973
|
+
try {
|
|
16974
|
+
parsed = JSON.parse(raw);
|
|
16975
|
+
} catch {
|
|
16976
|
+
return null;
|
|
16977
|
+
}
|
|
16978
|
+
if (!Array.isArray(parsed)) return null;
|
|
16979
|
+
const column = JSON.stringify(
|
|
16980
|
+
await encryptToolCallEvents(
|
|
16981
|
+
parsed,
|
|
16982
|
+
address,
|
|
16983
|
+
signMessage,
|
|
16984
|
+
embeddedWalletSigner
|
|
16985
|
+
)
|
|
16986
|
+
);
|
|
16987
|
+
return column === JSON.stringify(parsed) ? null : column;
|
|
16988
|
+
}
|
|
16989
|
+
async function encryptToolCallEventsOp(ctx) {
|
|
16990
|
+
const { walletAddress: address, signMessage, embeddedWalletSigner } = ctx;
|
|
16991
|
+
if (!address || !signMessage) return 0;
|
|
16992
|
+
if (!await requestEncryptionKey(address, signMessage, embeddedWalletSigner)) return 0;
|
|
16993
|
+
if (!hasEncryptionKey(address)) return 0;
|
|
16994
|
+
if (!await savedKeyOpensExistingData(ctx, address, signMessage, embeddedWalletSigner)) {
|
|
16995
|
+
return 0;
|
|
16996
|
+
}
|
|
16997
|
+
const candidateIds = await ctx.messagesCollection.query(
|
|
16998
|
+
import_watermelondb2.Q.where("tool_call_events", import_watermelondb2.Q.notEq(null)),
|
|
16999
|
+
import_watermelondb2.Q.where("tool_call_events", import_watermelondb2.Q.notIn(["", "[]"]))
|
|
17000
|
+
).fetchIds();
|
|
17001
|
+
let encrypted = 0;
|
|
17002
|
+
for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
|
|
17003
|
+
const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
|
|
17004
|
+
const rows = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).unsafeFetchRaw();
|
|
17005
|
+
const repairs = /* @__PURE__ */ new Map();
|
|
17006
|
+
for (const row of rows) {
|
|
17007
|
+
const column = await encryptedToolCallEventsColumn(
|
|
17008
|
+
row.tool_call_events,
|
|
17009
|
+
address,
|
|
17010
|
+
signMessage,
|
|
17011
|
+
embeddedWalletSigner
|
|
17012
|
+
);
|
|
17013
|
+
if (column !== null) repairs.set(String(row.id), { raw: row.tool_call_events, column });
|
|
17014
|
+
}
|
|
17015
|
+
if (repairs.size === 0) continue;
|
|
17016
|
+
await ctx.database.write(async () => {
|
|
17017
|
+
const messages = (await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf([...repairs.keys()]))).fetch()).filter(
|
|
17018
|
+
(message) => message._raw.tool_call_events === repairs.get(message.id)?.raw
|
|
17019
|
+
);
|
|
17020
|
+
if (messages.length === 0) return;
|
|
17021
|
+
const conversationIds = [...new Set(messages.map((message) => message.conversationId))];
|
|
17022
|
+
const conversations = await ctx.conversationsCollection.query(import_watermelondb2.Q.where("conversation_id", import_watermelondb2.Q.oneOf(conversationIds))).fetch();
|
|
17023
|
+
await ctx.database.batch(
|
|
17024
|
+
...messages.map(
|
|
17025
|
+
(message) => message.prepareUpdate((msg) => {
|
|
17026
|
+
msg._setRaw("tool_call_events", repairs.get(message.id).column);
|
|
17027
|
+
})
|
|
17028
|
+
),
|
|
17029
|
+
...conversations.map((conversation) => conversation.prepareUpdate(() => {
|
|
17030
|
+
}))
|
|
17031
|
+
);
|
|
17032
|
+
encrypted += messages.length;
|
|
17033
|
+
});
|
|
17034
|
+
}
|
|
17035
|
+
return encrypted;
|
|
17036
|
+
}
|
|
17037
|
+
async function savedKeyOpensExistingData(ctx, address, signMessage, embeddedWalletSigner) {
|
|
17038
|
+
const v3Probe = await findEncryptedContent(ctx, "enc:v3:%");
|
|
17039
|
+
if (v3Probe) {
|
|
17040
|
+
const { status } = await decryptFieldDetailed(v3Probe, address);
|
|
17041
|
+
if (status !== "auth_mismatch" && status !== "key_missing") return true;
|
|
17042
|
+
return refreshEncryptionKeyIfMatches(address, v3Probe, signMessage, embeddedWalletSigner);
|
|
17043
|
+
}
|
|
17044
|
+
const v2Probe = await findEncryptedContent(ctx, "enc:v2:%");
|
|
17045
|
+
if (!v2Probe) return true;
|
|
17046
|
+
return refreshEncryptionKeyIfMatches(address, v2Probe, signMessage, embeddedWalletSigner);
|
|
17047
|
+
}
|
|
17048
|
+
async function findEncryptedContent(ctx, pattern) {
|
|
17049
|
+
const [row] = await ctx.messagesCollection.query(import_watermelondb2.Q.where("content", import_watermelondb2.Q.like(pattern)), import_watermelondb2.Q.take(1)).unsafeFetchRaw();
|
|
17050
|
+
return row ? String(row.content) : null;
|
|
17051
|
+
}
|
|
16904
17052
|
async function updateMessageErrorOp(ctx, uniqueId, error) {
|
|
16905
17053
|
let message;
|
|
16906
17054
|
try {
|
|
@@ -17044,6 +17192,95 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
17044
17192
|
})
|
|
17045
17193
|
);
|
|
17046
17194
|
}
|
|
17195
|
+
var CHUNK_VECTOR_BATCH_SIZE = 50;
|
|
17196
|
+
var CHUNK_SCAN_YIELD_BUDGET_MS = 12;
|
|
17197
|
+
var hasEmbeddingSql = `(coalesce("chunks", '') != '' or coalesce("vector", '') != '')`;
|
|
17198
|
+
function toChunkCandidateKey(raw) {
|
|
17199
|
+
return {
|
|
17200
|
+
id: raw.id,
|
|
17201
|
+
conversationId: String(raw.conversation_id),
|
|
17202
|
+
version: Number(raw.updated_at) || 0,
|
|
17203
|
+
embeddingModel: raw.embedding_model ?? null
|
|
17204
|
+
};
|
|
17205
|
+
}
|
|
17206
|
+
async function fetchRowsByIds(ctx, ids) {
|
|
17207
|
+
if (ids.length === 0) return [];
|
|
17208
|
+
return await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(ids))).unsafeFetchRaw();
|
|
17209
|
+
}
|
|
17210
|
+
async function projectedChunkRowSource(ctx, filter) {
|
|
17211
|
+
const clauses = [
|
|
17212
|
+
`"history"."_status" is not 'deleted'`,
|
|
17213
|
+
hasEmbeddingSql,
|
|
17214
|
+
`exists (select 1 from "conversations" where "conversations"."conversation_id" = "history"."conversation_id" and "conversations"."is_deleted" = 0 and "conversations"."_status" is not 'deleted')`
|
|
17215
|
+
];
|
|
17216
|
+
const args = [];
|
|
17217
|
+
if (filter.conversationId !== void 0) {
|
|
17218
|
+
clauses.push(`"history"."conversation_id" = ?`);
|
|
17219
|
+
args.push(filter.conversationId);
|
|
17220
|
+
}
|
|
17221
|
+
if (filter.excludeConversationId !== void 0) {
|
|
17222
|
+
clauses.push(`"history"."conversation_id" != ?`);
|
|
17223
|
+
args.push(filter.excludeConversationId);
|
|
17224
|
+
}
|
|
17225
|
+
const keyRows = await ctx.messagesCollection.query(
|
|
17226
|
+
import_watermelondb2.Q.unsafeSqlQuery(
|
|
17227
|
+
`select "id", "conversation_id", "updated_at", "embedding_model" from "history" where ${clauses.join(" and ")}`,
|
|
17228
|
+
args
|
|
17229
|
+
)
|
|
17230
|
+
).unsafeFetchRaw();
|
|
17231
|
+
return {
|
|
17232
|
+
keys: keyRows.map(toChunkCandidateKey),
|
|
17233
|
+
loadVectorRows: async (ids) => {
|
|
17234
|
+
if (ids.length === 0) return [];
|
|
17235
|
+
return await ctx.messagesCollection.query(
|
|
17236
|
+
import_watermelondb2.Q.unsafeSqlQuery(
|
|
17237
|
+
`select "id", "updated_at", "chunks", "vector" from "history" where "_status" is not 'deleted' and "id" in (${ids.map(() => "?").join(",")})`,
|
|
17238
|
+
ids
|
|
17239
|
+
)
|
|
17240
|
+
).unsafeFetchRaw();
|
|
17241
|
+
},
|
|
17242
|
+
loadFullRows: (ids) => fetchRowsByIds(ctx, ids)
|
|
17243
|
+
};
|
|
17244
|
+
}
|
|
17245
|
+
async function fullScanChunkRowSource(ctx, filter) {
|
|
17246
|
+
const activeConversations = await ctx.conversationsCollection.query(import_watermelondb2.Q.where("is_deleted", false)).fetch();
|
|
17247
|
+
const activeConversationIds = new Set(
|
|
17248
|
+
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
17249
|
+
);
|
|
17250
|
+
const queryConditions = filter.conversationId !== void 0 ? [import_watermelondb2.Q.where("conversation_id", filter.conversationId)] : [];
|
|
17251
|
+
const rows = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
17252
|
+
const rowsById = /* @__PURE__ */ new Map();
|
|
17253
|
+
for (const row of rows) {
|
|
17254
|
+
const conversationId = String(row.conversation_id);
|
|
17255
|
+
if (!activeConversationIds.has(conversationId)) continue;
|
|
17256
|
+
if (filter.excludeConversationId !== void 0 && conversationId === filter.excludeConversationId) {
|
|
17257
|
+
continue;
|
|
17258
|
+
}
|
|
17259
|
+
if (!row.chunks && !row.vector) continue;
|
|
17260
|
+
rowsById.set(row.id, row);
|
|
17261
|
+
}
|
|
17262
|
+
const pick = (ids) => Promise.resolve(
|
|
17263
|
+
ids.flatMap((id) => {
|
|
17264
|
+
const row = rowsById.get(id);
|
|
17265
|
+
return row ? [row] : [];
|
|
17266
|
+
})
|
|
17267
|
+
);
|
|
17268
|
+
return {
|
|
17269
|
+
keys: Array.from(rowsById.values(), toChunkCandidateKey),
|
|
17270
|
+
loadVectorRows: pick,
|
|
17271
|
+
loadFullRows: pick
|
|
17272
|
+
};
|
|
17273
|
+
}
|
|
17274
|
+
async function chunkRowSource(ctx, filter) {
|
|
17275
|
+
try {
|
|
17276
|
+
return await projectedChunkRowSource(ctx, filter);
|
|
17277
|
+
} catch (err) {
|
|
17278
|
+
getLogger().debug(
|
|
17279
|
+
"searchChunksOp: projected SQL unavailable, using full-load fallback: " + (err instanceof Error ? err.message : String(err))
|
|
17280
|
+
);
|
|
17281
|
+
return fullScanChunkRowSource(ctx, filter);
|
|
17282
|
+
}
|
|
17283
|
+
}
|
|
17047
17284
|
async function searchChunksOp(ctx, queryVector, options) {
|
|
17048
17285
|
const {
|
|
17049
17286
|
limit = 10,
|
|
@@ -17051,83 +17288,111 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
17051
17288
|
conversationId,
|
|
17052
17289
|
excludeConversationId,
|
|
17053
17290
|
embeddingModel,
|
|
17054
|
-
chunkCache
|
|
17291
|
+
chunkCache,
|
|
17292
|
+
onStats
|
|
17055
17293
|
} = options || {};
|
|
17056
|
-
const
|
|
17057
|
-
const
|
|
17058
|
-
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
17059
|
-
);
|
|
17060
|
-
const queryConditions = conversationId ? [import_watermelondb2.Q.where("conversation_id", conversationId)] : [];
|
|
17061
|
-
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
17294
|
+
const source = await chunkRowSource(ctx, { conversationId, excludeConversationId });
|
|
17295
|
+
const yieldIfDue = createTimeSliceYielder(CHUNK_SCAN_YIELD_BUDGET_MS);
|
|
17062
17296
|
const candidates = [];
|
|
17063
17297
|
let staleSkipped = 0;
|
|
17064
17298
|
let unreadableVectors = 0;
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
|
|
17069
|
-
|
|
17070
|
-
|
|
17071
|
-
|
|
17072
|
-
|
|
17073
|
-
|
|
17074
|
-
}
|
|
17299
|
+
let cacheHits = 0;
|
|
17300
|
+
const missIds = [];
|
|
17301
|
+
const orderById = /* @__PURE__ */ new Map();
|
|
17302
|
+
for (const [order, key] of source.keys.entries()) {
|
|
17303
|
+
await yieldIfDue();
|
|
17304
|
+
orderById.set(key.id, order);
|
|
17305
|
+
if (embeddingModel && key.embeddingModel !== null && key.embeddingModel !== embeddingModel) {
|
|
17306
|
+
staleSkipped++;
|
|
17307
|
+
continue;
|
|
17075
17308
|
}
|
|
17076
|
-
const
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
if (cached.chunks.length > 0) {
|
|
17080
|
-
for (let ci = 0; ci < cached.chunks.length; ci++) {
|
|
17081
|
-
const vec = cached.chunks[ci];
|
|
17082
|
-
if (vec.length === 0) continue;
|
|
17083
|
-
const similarity = cosineSimilarity(queryVector, vec);
|
|
17084
|
-
if (similarity >= minSimilarity) {
|
|
17085
|
-
candidates.push({
|
|
17086
|
-
message,
|
|
17087
|
-
similarity,
|
|
17088
|
-
chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
|
|
17089
|
-
});
|
|
17090
|
-
}
|
|
17091
|
-
}
|
|
17092
|
-
} else if (cached.fallback) {
|
|
17093
|
-
const similarity = cosineSimilarity(queryVector, cached.fallback);
|
|
17094
|
-
if (similarity >= minSimilarity) {
|
|
17095
|
-
candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
|
|
17096
|
-
}
|
|
17097
|
-
}
|
|
17309
|
+
const cached = chunkCache?.get(key.id);
|
|
17310
|
+
if (!cached || cached.version !== key.version) {
|
|
17311
|
+
missIds.push(key.id);
|
|
17098
17312
|
continue;
|
|
17099
17313
|
}
|
|
17100
|
-
|
|
17101
|
-
if (chunks
|
|
17102
|
-
|
|
17103
|
-
|
|
17104
|
-
unreadableVectors++;
|
|
17105
|
-
})
|
|
17106
|
-
);
|
|
17107
|
-
chunkCache?.set(message.id, { version, chunks: vectors });
|
|
17108
|
-
for (let ci = 0; ci < chunks.length; ci++) {
|
|
17109
|
-
const vec = vectors[ci];
|
|
17314
|
+
cacheHits++;
|
|
17315
|
+
if (cached.chunks.length > 0) {
|
|
17316
|
+
for (let ci = 0; ci < cached.chunks.length; ci++) {
|
|
17317
|
+
const vec = cached.chunks[ci];
|
|
17110
17318
|
if (vec.length === 0) continue;
|
|
17111
17319
|
const similarity = cosineSimilarity(queryVector, vec);
|
|
17112
17320
|
if (similarity >= minSimilarity) {
|
|
17113
17321
|
candidates.push({
|
|
17114
|
-
|
|
17322
|
+
id: key.id,
|
|
17323
|
+
version: key.version,
|
|
17324
|
+
order,
|
|
17115
17325
|
similarity,
|
|
17116
|
-
chunkTextSource: { kind: "chunk",
|
|
17326
|
+
chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version: key.version }
|
|
17117
17327
|
});
|
|
17118
17328
|
}
|
|
17119
17329
|
}
|
|
17120
|
-
} else {
|
|
17121
|
-
const
|
|
17122
|
-
if (!messageVector || messageVector.length === 0) continue;
|
|
17123
|
-
const fallback = Float32Array.from(messageVector);
|
|
17124
|
-
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
17125
|
-
const similarity = cosineSimilarity(queryVector, fallback);
|
|
17330
|
+
} else if (cached.fallback) {
|
|
17331
|
+
const similarity = cosineSimilarity(queryVector, cached.fallback);
|
|
17126
17332
|
if (similarity >= minSimilarity) {
|
|
17127
|
-
candidates.push({
|
|
17333
|
+
candidates.push({
|
|
17334
|
+
id: key.id,
|
|
17335
|
+
version: key.version,
|
|
17336
|
+
order,
|
|
17337
|
+
similarity,
|
|
17338
|
+
chunkTextSource: { kind: "message" }
|
|
17339
|
+
});
|
|
17340
|
+
}
|
|
17341
|
+
}
|
|
17342
|
+
}
|
|
17343
|
+
let rowsFetched = 0;
|
|
17344
|
+
for (let offset = 0; offset < missIds.length; offset += CHUNK_VECTOR_BATCH_SIZE) {
|
|
17345
|
+
const rows = await source.loadVectorRows(
|
|
17346
|
+
missIds.slice(offset, offset + CHUNK_VECTOR_BATCH_SIZE)
|
|
17347
|
+
);
|
|
17348
|
+
rowsFetched += rows.length;
|
|
17349
|
+
for (const row of rows) {
|
|
17350
|
+
await yieldIfDue();
|
|
17351
|
+
const id = row.id;
|
|
17352
|
+
const version = Number(row.updated_at) || 0;
|
|
17353
|
+
const order = orderById.get(id) ?? Number.MAX_SAFE_INTEGER;
|
|
17354
|
+
const chunks = await readRawJsonField(row, "chunks", ctx.walletAddress);
|
|
17355
|
+
if (chunks && chunks.length > 0) {
|
|
17356
|
+
const vectors = chunks.map(
|
|
17357
|
+
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
17358
|
+
unreadableVectors++;
|
|
17359
|
+
})
|
|
17360
|
+
);
|
|
17361
|
+
chunkCache?.set(id, { version, chunks: vectors });
|
|
17362
|
+
for (let ci = 0; ci < chunks.length; ci++) {
|
|
17363
|
+
const vec = vectors[ci];
|
|
17364
|
+
if (vec.length === 0) continue;
|
|
17365
|
+
const similarity = cosineSimilarity(queryVector, vec);
|
|
17366
|
+
if (similarity >= minSimilarity) {
|
|
17367
|
+
candidates.push({
|
|
17368
|
+
id,
|
|
17369
|
+
version,
|
|
17370
|
+
order,
|
|
17371
|
+
similarity,
|
|
17372
|
+
chunkTextSource: { kind: "chunk", chunk: chunks[ci], siblings: chunks }
|
|
17373
|
+
});
|
|
17374
|
+
}
|
|
17375
|
+
}
|
|
17376
|
+
} else {
|
|
17377
|
+
const messageVector = await readRawJsonField(row, "vector", ctx.walletAddress);
|
|
17378
|
+
if (messageVector && messageVector.length > 0) {
|
|
17379
|
+
const fallback = Float32Array.from(messageVector);
|
|
17380
|
+
chunkCache?.set(id, { version, chunks: [], fallback });
|
|
17381
|
+
const similarity = cosineSimilarity(queryVector, fallback);
|
|
17382
|
+
if (similarity >= minSimilarity) {
|
|
17383
|
+
candidates.push({
|
|
17384
|
+
id,
|
|
17385
|
+
version,
|
|
17386
|
+
order,
|
|
17387
|
+
similarity,
|
|
17388
|
+
chunkTextSource: { kind: "message" }
|
|
17389
|
+
});
|
|
17390
|
+
}
|
|
17391
|
+
}
|
|
17128
17392
|
}
|
|
17129
17393
|
}
|
|
17130
17394
|
}
|
|
17395
|
+
onStats?.({ rowsScanned: source.keys.length, rowsFetched, cacheHits });
|
|
17131
17396
|
if (staleSkipped > 0) {
|
|
17132
17397
|
getLogger().warn(
|
|
17133
17398
|
`searchChunksOp: skipped ${staleSkipped} messages whose embedding model differs from the current model (${embeddingModel}) \u2014 re-embed via chunkAndEmbedAllMessages`
|
|
@@ -17138,12 +17403,17 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
17138
17403
|
`searchChunksOp: could not read ${unreadableVectors} chunk vectors and left them out of ranking \u2014 the stored value is corrupt, so those chunks stay unsearchable until the message is re-embedded via chunkAndEmbedAllMessages`
|
|
17139
17404
|
);
|
|
17140
17405
|
}
|
|
17141
|
-
const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
17142
|
-
const
|
|
17143
|
-
|
|
17406
|
+
const topK = candidates.sort((a, b) => b.similarity - a.similarity || a.order - b.order).slice(0, limit);
|
|
17407
|
+
const topIds = Array.from(new Set(topK.map((c) => c.id)));
|
|
17408
|
+
const fullRows = await source.loadFullRows(topIds);
|
|
17409
|
+
const rowById = new Map(fullRows.map((row) => [row.id, row]));
|
|
17410
|
+
const liveTopK = topK.filter((c) => {
|
|
17411
|
+
const row = rowById.get(c.id);
|
|
17412
|
+
return row !== void 0 && (Number(row.updated_at) || 0) === c.version;
|
|
17413
|
+
});
|
|
17144
17414
|
const storedById = new Map(
|
|
17145
17415
|
await Promise.all(
|
|
17146
|
-
Array.from(
|
|
17416
|
+
Array.from(rowById, async ([id, m]) => {
|
|
17147
17417
|
const stored = await messageRawToStored(
|
|
17148
17418
|
m,
|
|
17149
17419
|
ctx.walletAddress,
|
|
@@ -17156,24 +17426,24 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
17156
17426
|
);
|
|
17157
17427
|
const chunkStateByMsgId = /* @__PURE__ */ new Map();
|
|
17158
17428
|
const needsChunkText = /* @__PURE__ */ new Set();
|
|
17159
|
-
for (const c of
|
|
17160
|
-
if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.
|
|
17429
|
+
for (const c of liveTopK) {
|
|
17430
|
+
if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.id);
|
|
17161
17431
|
}
|
|
17162
17432
|
await Promise.all(
|
|
17163
17433
|
Array.from(needsChunkText, async (id) => {
|
|
17164
|
-
const m =
|
|
17434
|
+
const m = rowById.get(id);
|
|
17165
17435
|
const parsed = await readRawJsonField(m, "chunks", ctx.walletAddress);
|
|
17166
17436
|
const version = Number(m.updated_at) || 0;
|
|
17167
17437
|
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
17168
17438
|
})
|
|
17169
17439
|
);
|
|
17170
|
-
return
|
|
17171
|
-
const stored = { ...storedById.get(
|
|
17440
|
+
return liveTopK.map(({ id, similarity, chunkTextSource }) => {
|
|
17441
|
+
const stored = { ...storedById.get(id) };
|
|
17172
17442
|
let chunkText2;
|
|
17173
17443
|
if (chunkTextSource.kind === "chunk") {
|
|
17174
17444
|
chunkText2 = resolveChunkText(stored.content, chunkTextSource.chunk, chunkTextSource.siblings);
|
|
17175
17445
|
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
17176
|
-
const state = chunkStateByMsgId.get(
|
|
17446
|
+
const state = chunkStateByMsgId.get(id);
|
|
17177
17447
|
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
17178
17448
|
chunkText2 = resolveChunkText(stored.content, chunk, state?.chunks);
|
|
17179
17449
|
} else {
|
|
@@ -18269,13 +18539,35 @@ async function generateEmbedding(text12, options) {
|
|
|
18269
18539
|
if (total === void 0) return embedOne(text12, options, void 0);
|
|
18270
18540
|
return withDeadline((signal) => embedOne(text12, options, signal), total, "embedding");
|
|
18271
18541
|
}
|
|
18542
|
+
var inFlightByCache = /* @__PURE__ */ new WeakMap();
|
|
18272
18543
|
async function embedOne(text12, options, outer) {
|
|
18273
|
-
const {
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18544
|
+
const { cache } = options;
|
|
18545
|
+
if (!cache) return Array.from(await requestEmbedding(text12, options, outer));
|
|
18546
|
+
const cached = cache.get(text12);
|
|
18547
|
+
if (cached) return Array.from(cached);
|
|
18548
|
+
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
18549
|
+
inFlightByCache.set(cache, inFlight);
|
|
18550
|
+
const pending = inFlight.get(text12);
|
|
18551
|
+
if (pending) {
|
|
18552
|
+
try {
|
|
18553
|
+
return Array.from(await pending);
|
|
18554
|
+
} catch (err) {
|
|
18555
|
+
if (outer?.aborted) throw err;
|
|
18556
|
+
}
|
|
18557
|
+
}
|
|
18558
|
+
const request = requestEmbedding(text12, options, outer);
|
|
18559
|
+
inFlight.set(text12, request);
|
|
18560
|
+
try {
|
|
18561
|
+
const embedding = await request;
|
|
18562
|
+
cache.set(text12, embedding);
|
|
18563
|
+
return Array.from(embedding);
|
|
18564
|
+
} finally {
|
|
18565
|
+
if (inFlight.get(text12) === request) inFlight.delete(text12);
|
|
18278
18566
|
}
|
|
18567
|
+
}
|
|
18568
|
+
async function requestEmbedding(text12, options, outer) {
|
|
18569
|
+
const { baseUrl = BASE_URL, model } = options;
|
|
18570
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
18279
18571
|
const headers = {
|
|
18280
18572
|
...await resolveAuthHeaders(options, outer),
|
|
18281
18573
|
...taskTypeHeader(options.taskType)
|
|
@@ -18310,11 +18602,7 @@ async function embedOne(text12, options, outer) {
|
|
|
18310
18602
|
totalTokens: response.data.usage.total_tokens ?? 0
|
|
18311
18603
|
});
|
|
18312
18604
|
}
|
|
18313
|
-
|
|
18314
|
-
if (cache) {
|
|
18315
|
-
cache.set(text12, f32Embedding);
|
|
18316
|
-
}
|
|
18317
|
-
return Array.from(f32Embedding);
|
|
18605
|
+
return Float32Array.from(embedding);
|
|
18318
18606
|
}
|
|
18319
18607
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
18320
18608
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
@@ -28737,9 +29025,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
28737
29025
|
const updatedMs = updatedAt.getTime();
|
|
28738
29026
|
if (!Number.isFinite(updatedMs)) return noDate;
|
|
28739
29027
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
28740
|
-
const
|
|
28741
|
-
if (!Number.isFinite(
|
|
28742
|
-
const ageDays2 = Math.max(0, (
|
|
29028
|
+
const nowMs2 = now.getTime();
|
|
29029
|
+
if (!Number.isFinite(nowMs2)) return noDate;
|
|
29030
|
+
const ageDays2 = Math.max(0, (nowMs2 - updatedMs) / DAY_MS2);
|
|
28743
29031
|
const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
|
|
28744
29032
|
const floor = opts.floor ?? DEFAULT_FLOOR;
|
|
28745
29033
|
const decay = perYearDecay * (ageDays2 / 365);
|
|
@@ -29248,9 +29536,6 @@ function createVaultEmbeddingCache(maxSize = DEFAULT_VAULT_CACHE_SIZE) {
|
|
|
29248
29536
|
|
|
29249
29537
|
// src/lib/memoryVault/searchTool.ts
|
|
29250
29538
|
var DEFAULT_RERANK_TOP_N = 5;
|
|
29251
|
-
function nowMs() {
|
|
29252
|
-
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
29253
|
-
}
|
|
29254
29539
|
var warnedProgrammaticDecomposeIgnored = false;
|
|
29255
29540
|
function normalizeEventTimeKind(kind) {
|
|
29256
29541
|
return kind === "point" || kind === "range" || kind === "ongoing" ? kind : null;
|
|
@@ -32141,6 +32426,32 @@ function rankProfileCandidates(inputs, now = Date.now(), options = {}) {
|
|
|
32141
32426
|
return ranked;
|
|
32142
32427
|
}
|
|
32143
32428
|
|
|
32429
|
+
// src/lib/db/chat/embeddingCache.ts
|
|
32430
|
+
var MaskScopedEmbeddingCache = class extends Map {
|
|
32431
|
+
constructor(inner, masked) {
|
|
32432
|
+
super();
|
|
32433
|
+
this.inner = inner;
|
|
32434
|
+
this.masked = masked;
|
|
32435
|
+
}
|
|
32436
|
+
key(text12) {
|
|
32437
|
+
return `${this.masked ? "m" : "r"}:${text12}`;
|
|
32438
|
+
}
|
|
32439
|
+
get(text12) {
|
|
32440
|
+
return this.inner.get(this.key(text12));
|
|
32441
|
+
}
|
|
32442
|
+
set(text12, value) {
|
|
32443
|
+
this.inner.set(this.key(text12), value);
|
|
32444
|
+
return this;
|
|
32445
|
+
}
|
|
32446
|
+
};
|
|
32447
|
+
var scopedViews = /* @__PURE__ */ new WeakMap();
|
|
32448
|
+
function maskScopedEmbeddingCache(cache, masked) {
|
|
32449
|
+
const views = scopedViews.get(cache) ?? {};
|
|
32450
|
+
scopedViews.set(cache, views);
|
|
32451
|
+
const slot = masked ? "masked" : "raw";
|
|
32452
|
+
return views[slot] ?? (views[slot] = new MaskScopedEmbeddingCache(cache, masked));
|
|
32453
|
+
}
|
|
32454
|
+
|
|
32144
32455
|
// src/lib/memory/queryTemporal.ts
|
|
32145
32456
|
var RELATIVE_DAY_ENTRIES = [
|
|
32146
32457
|
[/\btoday\b/, "today", 0],
|
|
@@ -32348,9 +32659,6 @@ function scoreEventTimeOverlap(memoryStart, memoryEnd, memoryKind, window2) {
|
|
|
32348
32659
|
var DEFAULT_LIMIT = 8;
|
|
32349
32660
|
var DEFAULT_BUDGET = "low";
|
|
32350
32661
|
var DEFAULT_FACT_MIN_SCORE = 0.1;
|
|
32351
|
-
function nowMs2() {
|
|
32352
|
-
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
32353
|
-
}
|
|
32354
32662
|
var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
32355
32663
|
var DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS = 8e3;
|
|
32356
32664
|
function flagsForBudget(budget) {
|
|
@@ -32388,12 +32696,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
32388
32696
|
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
32389
32697
|
const embeddingOptions = {
|
|
32390
32698
|
...ctx.embeddingOptions,
|
|
32391
|
-
taskType: "memory_recall_embed"
|
|
32699
|
+
taskType: "memory_recall_embed",
|
|
32700
|
+
...options.embeddingCache && !ctx.embeddingOptions.cache && {
|
|
32701
|
+
cache: maskScopedEmbeddingCache(
|
|
32702
|
+
options.embeddingCache,
|
|
32703
|
+
Boolean(ctx.embeddingOptions.maskInput)
|
|
32704
|
+
)
|
|
32705
|
+
}
|
|
32392
32706
|
};
|
|
32393
|
-
const t0 =
|
|
32707
|
+
const t0 = nowMs();
|
|
32394
32708
|
let prepMs = 0;
|
|
32395
32709
|
let factLaneMs = 0;
|
|
32396
32710
|
let chunkLaneMs = 0;
|
|
32711
|
+
let chunkStats;
|
|
32397
32712
|
let fuseMs = 0;
|
|
32398
32713
|
const factResults = [];
|
|
32399
32714
|
const chunkResults = [];
|
|
@@ -32448,6 +32763,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
32448
32763
|
...decryptLastRan !== void 0 && { decryptLast: decryptLastRan },
|
|
32449
32764
|
...vaultRowsDecrypted !== void 0 && { vaultRowsDecrypted },
|
|
32450
32765
|
...vaultRowsEmbedded !== void 0 && { vaultRowsEmbedded },
|
|
32766
|
+
...chunkStats && {
|
|
32767
|
+
chunkRowsScanned: chunkStats.rowsScanned,
|
|
32768
|
+
chunkRowsFetched: chunkStats.rowsFetched,
|
|
32769
|
+
chunkCacheHits: chunkStats.cacheHits
|
|
32770
|
+
},
|
|
32451
32771
|
factCount: factResults.length,
|
|
32452
32772
|
chunkCount: chunkResults.length,
|
|
32453
32773
|
admittedCount: admitted.length,
|
|
@@ -32459,7 +32779,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
32459
32779
|
temporalLaneCount,
|
|
32460
32780
|
emptyReason: emptyReasonFor(admitted.length, laneRan),
|
|
32461
32781
|
timings: {
|
|
32462
|
-
total:
|
|
32782
|
+
total: nowMs() - t0,
|
|
32463
32783
|
prep: prepMs,
|
|
32464
32784
|
factLane: factLaneMs,
|
|
32465
32785
|
rerank: rerankMs,
|
|
@@ -32481,14 +32801,14 @@ async function recall(query, ctx, options = {}) {
|
|
|
32481
32801
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
32482
32802
|
const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
|
|
32483
32803
|
const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
|
|
32484
|
-
const prepStart =
|
|
32804
|
+
const prepStart = nowMs();
|
|
32485
32805
|
let sharedEmbedMs = 0;
|
|
32486
32806
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
32487
32807
|
needsChunkEmbedding ? generateEmbedding(query, {
|
|
32488
32808
|
...embeddingOptions,
|
|
32489
32809
|
totalTimeoutMs: queryEmbedTotalTimeoutMs
|
|
32490
32810
|
}).finally(() => {
|
|
32491
|
-
sharedEmbedMs =
|
|
32811
|
+
sharedEmbedMs = nowMs() - prepStart;
|
|
32492
32812
|
}).then((vec) => {
|
|
32493
32813
|
if (vec.length === 0) {
|
|
32494
32814
|
getLogger().warn(
|
|
@@ -32521,11 +32841,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
32521
32841
|
() => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
32522
32842
|
) : Promise.resolve([])
|
|
32523
32843
|
]);
|
|
32524
|
-
prepMs =
|
|
32844
|
+
prepMs = nowMs() - prepStart;
|
|
32525
32845
|
graphLaneCount = entityRanking.length;
|
|
32526
32846
|
temporalLaneCount = temporalRanking.length;
|
|
32527
32847
|
if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
|
|
32528
|
-
const factStart =
|
|
32848
|
+
const factStart = nowMs();
|
|
32529
32849
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
32530
32850
|
factFloor = vaultMinScore;
|
|
32531
32851
|
const {
|
|
@@ -32601,11 +32921,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
32601
32921
|
factLaneRankedOnCosine = factRankedOnCosine;
|
|
32602
32922
|
decryptLastRan = factDecryptLast;
|
|
32603
32923
|
vaultRowsDecrypted = factRowsDecrypted;
|
|
32604
|
-
factLaneMs =
|
|
32924
|
+
factLaneMs = nowMs() - factStart;
|
|
32605
32925
|
}
|
|
32606
32926
|
if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
|
|
32607
32927
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
32608
|
-
const chunkStart =
|
|
32928
|
+
const chunkStart = nowMs();
|
|
32609
32929
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
32610
32930
|
chunkFloor = chunkMinScore;
|
|
32611
32931
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
@@ -32616,12 +32936,15 @@ async function recall(query, ctx, options = {}) {
|
|
|
32616
32936
|
...options.excludeConversationId && {
|
|
32617
32937
|
excludeConversationId: options.excludeConversationId
|
|
32618
32938
|
},
|
|
32619
|
-
...ctx.chunkCache && { chunkCache: ctx.chunkCache }
|
|
32939
|
+
...ctx.chunkCache && { chunkCache: ctx.chunkCache },
|
|
32940
|
+
onStats: (stats) => {
|
|
32941
|
+
chunkStats = stats;
|
|
32942
|
+
}
|
|
32620
32943
|
});
|
|
32621
32944
|
chunkResults.push(...dedupeBy(results, (r) => r.chunkText.trim()));
|
|
32622
|
-
chunkLaneMs =
|
|
32945
|
+
chunkLaneMs = nowMs() - chunkStart;
|
|
32623
32946
|
}
|
|
32624
|
-
const fuseStart =
|
|
32947
|
+
const fuseStart = nowMs();
|
|
32625
32948
|
if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
|
|
32626
32949
|
const memories2 = [
|
|
32627
32950
|
...factResults.map((r) => toFactMemory(r, options.now)),
|
|
@@ -32629,7 +32952,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
32629
32952
|
];
|
|
32630
32953
|
memories2.sort((a, b) => b.score - a.score);
|
|
32631
32954
|
const candidateCount = factResults.length + chunkResults.length;
|
|
32632
|
-
fuseMs =
|
|
32955
|
+
fuseMs = nowMs() - fuseStart;
|
|
32633
32956
|
const admitted = memories2.slice(0, limit);
|
|
32634
32957
|
hitLimit = memories2.length > limit;
|
|
32635
32958
|
emitDiagnostics(candidateCount, admitted);
|
|
@@ -32693,7 +33016,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
32693
33016
|
memories = selection.out;
|
|
32694
33017
|
}
|
|
32695
33018
|
hitLimit = selection.cut;
|
|
32696
|
-
fuseMs =
|
|
33019
|
+
fuseMs = nowMs() - fuseStart;
|
|
32697
33020
|
emitDiagnostics(byId.size, memories);
|
|
32698
33021
|
return {
|
|
32699
33022
|
memories,
|
|
@@ -37687,6 +38010,7 @@ export {
|
|
|
37687
38010
|
encryptDataBatch,
|
|
37688
38011
|
encryptDataBytes,
|
|
37689
38012
|
encryptDataWithKey,
|
|
38013
|
+
encryptToolCallEventsOp,
|
|
37690
38014
|
estimateMessagesTokens,
|
|
37691
38015
|
estimateTokens,
|
|
37692
38016
|
exportPublicKey,
|