@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.cjs
CHANGED
|
@@ -16424,6 +16424,7 @@ __export(index_exports, {
|
|
|
16424
16424
|
encryptDataBatch: () => encryptDataBatch,
|
|
16425
16425
|
encryptDataBytes: () => encryptDataBytes,
|
|
16426
16426
|
encryptDataWithKey: () => encryptDataWithKey,
|
|
16427
|
+
encryptToolCallEventsOp: () => encryptToolCallEventsOp,
|
|
16427
16428
|
estimateMessagesTokens: () => estimateMessagesTokens,
|
|
16428
16429
|
estimateTokens: () => estimateTokens,
|
|
16429
16430
|
exportPublicKey: () => exportPublicKey,
|
|
@@ -17668,6 +17669,35 @@ function decodeChunkVector(vector, onMalformed) {
|
|
|
17668
17669
|
}
|
|
17669
17670
|
}
|
|
17670
17671
|
|
|
17672
|
+
// src/lib/scheduling.ts
|
|
17673
|
+
function nowMs() {
|
|
17674
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
17675
|
+
}
|
|
17676
|
+
function yieldToEventLoop() {
|
|
17677
|
+
const scheduler = globalThis.scheduler;
|
|
17678
|
+
if (typeof scheduler?.yield === "function") return scheduler.yield();
|
|
17679
|
+
if (typeof MessageChannel === "function") {
|
|
17680
|
+
return new Promise((resolve) => {
|
|
17681
|
+
const channel = new MessageChannel();
|
|
17682
|
+
channel.port1.onmessage = () => {
|
|
17683
|
+
channel.port1.close();
|
|
17684
|
+
channel.port2.close();
|
|
17685
|
+
resolve();
|
|
17686
|
+
};
|
|
17687
|
+
channel.port2.postMessage(null);
|
|
17688
|
+
});
|
|
17689
|
+
}
|
|
17690
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
17691
|
+
}
|
|
17692
|
+
function createTimeSliceYielder(budgetMs) {
|
|
17693
|
+
let sliceStart = nowMs();
|
|
17694
|
+
return async () => {
|
|
17695
|
+
if (nowMs() - sliceStart < budgetMs) return;
|
|
17696
|
+
await yieldToEventLoop();
|
|
17697
|
+
sliceStart = nowMs();
|
|
17698
|
+
};
|
|
17699
|
+
}
|
|
17700
|
+
|
|
17671
17701
|
// src/lib/db/encryption-utils.ts
|
|
17672
17702
|
init_logger();
|
|
17673
17703
|
var ENCRYPTION_PREFIX = "enc:v3:";
|
|
@@ -17814,6 +17844,12 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
17814
17844
|
const encryptedChunks = msg.chunks ? await encryptJsonField(msg.chunks, address, signMessage, embeddedWalletSigner, true) : void 0;
|
|
17815
17845
|
const encryptedSources = msg.sources ? await encryptJsonField(msg.sources, address, signMessage, embeddedWalletSigner, true) : void 0;
|
|
17816
17846
|
const encryptedThoughtProcess = msg.thoughtProcess ? await encryptJsonField(msg.thoughtProcess, address, signMessage, embeddedWalletSigner, true) : void 0;
|
|
17847
|
+
const encryptedToolCallEvents = Array.isArray(msg.toolCallEvents) ? await encryptToolCallEvents(
|
|
17848
|
+
msg.toolCallEvents,
|
|
17849
|
+
address,
|
|
17850
|
+
signMessage,
|
|
17851
|
+
embeddedWalletSigner
|
|
17852
|
+
) : void 0;
|
|
17817
17853
|
return {
|
|
17818
17854
|
...message,
|
|
17819
17855
|
...encryptedContent !== void 0 && { content: encryptedContent },
|
|
@@ -17821,13 +17857,31 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
17821
17857
|
...encryptedVector !== void 0 && { vector: encryptedVector },
|
|
17822
17858
|
...encryptedChunks !== void 0 && { chunks: encryptedChunks },
|
|
17823
17859
|
...encryptedSources !== void 0 && { sources: encryptedSources },
|
|
17824
|
-
...encryptedThoughtProcess !== void 0 && { thoughtProcess: encryptedThoughtProcess }
|
|
17860
|
+
...encryptedThoughtProcess !== void 0 && { thoughtProcess: encryptedThoughtProcess },
|
|
17861
|
+
...encryptedToolCallEvents !== void 0 && { toolCallEvents: encryptedToolCallEvents }
|
|
17825
17862
|
};
|
|
17826
17863
|
} catch (error) {
|
|
17827
17864
|
getLogger().warn("Failed to encrypt message fields:", error);
|
|
17828
17865
|
throw error;
|
|
17829
17866
|
}
|
|
17830
17867
|
}
|
|
17868
|
+
function mapToolCallPayloads(events, transform) {
|
|
17869
|
+
return Promise.all(
|
|
17870
|
+
events.map(async (event) => {
|
|
17871
|
+
if (!event || typeof event !== "object") return event;
|
|
17872
|
+
const mapped = { ...event };
|
|
17873
|
+
if (typeof event.arguments === "string") mapped.arguments = await transform(event.arguments);
|
|
17874
|
+
if (typeof event.output === "string") mapped.output = await transform(event.output);
|
|
17875
|
+
return mapped;
|
|
17876
|
+
})
|
|
17877
|
+
);
|
|
17878
|
+
}
|
|
17879
|
+
function encryptToolCallEvents(events, address, signMessage, embeddedWalletSigner) {
|
|
17880
|
+
return mapToolCallPayloads(
|
|
17881
|
+
events,
|
|
17882
|
+
(value) => encryptField(value, address, signMessage, embeddedWalletSigner, true)
|
|
17883
|
+
);
|
|
17884
|
+
}
|
|
17831
17885
|
async function decryptMaybeJsonFieldDetailed(value, address) {
|
|
17832
17886
|
if (value === void 0) return { value: void 0, status: "plaintext" };
|
|
17833
17887
|
if (value === null) return { value, status: "plaintext" };
|
|
@@ -17913,6 +17967,10 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
17913
17967
|
message.thoughtProcess,
|
|
17914
17968
|
address
|
|
17915
17969
|
);
|
|
17970
|
+
const toolCallEventsResult = await decryptMaybeJsonFieldDetailed(
|
|
17971
|
+
message.toolCallEvents,
|
|
17972
|
+
address
|
|
17973
|
+
);
|
|
17916
17974
|
let decryptionStatus;
|
|
17917
17975
|
let refreshProbe;
|
|
17918
17976
|
const consider = (status, probe) => {
|
|
@@ -17931,6 +17989,14 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
17931
17989
|
if (thoughtProcessResult.probe) {
|
|
17932
17990
|
consider(thoughtProcessResult.status, thoughtProcessResult.probe);
|
|
17933
17991
|
}
|
|
17992
|
+
if (toolCallEventsResult.probe) {
|
|
17993
|
+
consider(toolCallEventsResult.status, toolCallEventsResult.probe);
|
|
17994
|
+
}
|
|
17995
|
+
const toolCallEvents = Array.isArray(toolCallEventsResult.value) ? await mapToolCallPayloads(toolCallEventsResult.value, async (value) => {
|
|
17996
|
+
const detailed = await decryptFieldDetailed(value, address);
|
|
17997
|
+
consider(detailed.status, isEncrypted(value) ? value : void 0);
|
|
17998
|
+
return detailed.value;
|
|
17999
|
+
}) : void 0;
|
|
17934
18000
|
const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
|
|
17935
18001
|
const result = {
|
|
17936
18002
|
...message,
|
|
@@ -17939,7 +18005,8 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
17939
18005
|
vector: vectorResult.value,
|
|
17940
18006
|
chunks: chunksResult.value,
|
|
17941
18007
|
sources: sourcesResult.value,
|
|
17942
|
-
thoughtProcess: thoughtProcessResult.value
|
|
18008
|
+
thoughtProcess: thoughtProcessResult.value,
|
|
18009
|
+
toolCallEvents
|
|
17943
18010
|
};
|
|
17944
18011
|
if (statusForConsumer) {
|
|
17945
18012
|
result.decryptionStatus = statusForConsumer;
|
|
@@ -18505,7 +18572,7 @@ async function updateMessageChunksOp(ctx, uniqueId, chunks, embeddingModel) {
|
|
|
18505
18572
|
});
|
|
18506
18573
|
return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
18507
18574
|
}
|
|
18508
|
-
var
|
|
18575
|
+
var RAW_REPAIR_PAGE_SIZE = 100;
|
|
18509
18576
|
function chunksWithoutText(raw) {
|
|
18510
18577
|
if (typeof raw !== "string") return null;
|
|
18511
18578
|
let parsed;
|
|
@@ -18528,8 +18595,8 @@ function chunksWithoutText(raw) {
|
|
|
18528
18595
|
async function stripLegacyChunkTextOp(ctx) {
|
|
18529
18596
|
const candidateIds = await ctx.messagesCollection.query(import_watermelondb2.Q.where("chunks", import_watermelondb2.Q.like(`%${import_watermelondb2.Q.sanitizeLikeString('"text":')}%`))).fetchIds();
|
|
18530
18597
|
let stripped = 0;
|
|
18531
|
-
for (let start = 0; start < candidateIds.length; start +=
|
|
18532
|
-
const pageIds = candidateIds.slice(start, start +
|
|
18598
|
+
for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
|
|
18599
|
+
const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
|
|
18533
18600
|
const rows = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).unsafeFetchRaw();
|
|
18534
18601
|
const changedIds = rows.filter((row) => chunksWithoutText(row.chunks) !== null).map((row) => String(row.id));
|
|
18535
18602
|
if (changedIds.length === 0) continue;
|
|
@@ -18553,6 +18620,88 @@ async function stripLegacyChunkTextOp(ctx) {
|
|
|
18553
18620
|
}
|
|
18554
18621
|
return stripped;
|
|
18555
18622
|
}
|
|
18623
|
+
async function encryptedToolCallEventsColumn(raw, address, signMessage, embeddedWalletSigner) {
|
|
18624
|
+
if (typeof raw !== "string") return null;
|
|
18625
|
+
let parsed;
|
|
18626
|
+
try {
|
|
18627
|
+
parsed = JSON.parse(raw);
|
|
18628
|
+
} catch {
|
|
18629
|
+
return null;
|
|
18630
|
+
}
|
|
18631
|
+
if (!Array.isArray(parsed)) return null;
|
|
18632
|
+
const column = JSON.stringify(
|
|
18633
|
+
await encryptToolCallEvents(
|
|
18634
|
+
parsed,
|
|
18635
|
+
address,
|
|
18636
|
+
signMessage,
|
|
18637
|
+
embeddedWalletSigner
|
|
18638
|
+
)
|
|
18639
|
+
);
|
|
18640
|
+
return column === JSON.stringify(parsed) ? null : column;
|
|
18641
|
+
}
|
|
18642
|
+
async function encryptToolCallEventsOp(ctx) {
|
|
18643
|
+
const { walletAddress: address, signMessage, embeddedWalletSigner } = ctx;
|
|
18644
|
+
if (!address || !signMessage) return 0;
|
|
18645
|
+
if (!await requestEncryptionKey(address, signMessage, embeddedWalletSigner)) return 0;
|
|
18646
|
+
if (!hasEncryptionKey(address)) return 0;
|
|
18647
|
+
if (!await savedKeyOpensExistingData(ctx, address, signMessage, embeddedWalletSigner)) {
|
|
18648
|
+
return 0;
|
|
18649
|
+
}
|
|
18650
|
+
const candidateIds = await ctx.messagesCollection.query(
|
|
18651
|
+
import_watermelondb2.Q.where("tool_call_events", import_watermelondb2.Q.notEq(null)),
|
|
18652
|
+
import_watermelondb2.Q.where("tool_call_events", import_watermelondb2.Q.notIn(["", "[]"]))
|
|
18653
|
+
).fetchIds();
|
|
18654
|
+
let encrypted = 0;
|
|
18655
|
+
for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
|
|
18656
|
+
const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
|
|
18657
|
+
const rows = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).unsafeFetchRaw();
|
|
18658
|
+
const repairs = /* @__PURE__ */ new Map();
|
|
18659
|
+
for (const row of rows) {
|
|
18660
|
+
const column = await encryptedToolCallEventsColumn(
|
|
18661
|
+
row.tool_call_events,
|
|
18662
|
+
address,
|
|
18663
|
+
signMessage,
|
|
18664
|
+
embeddedWalletSigner
|
|
18665
|
+
);
|
|
18666
|
+
if (column !== null) repairs.set(String(row.id), { raw: row.tool_call_events, column });
|
|
18667
|
+
}
|
|
18668
|
+
if (repairs.size === 0) continue;
|
|
18669
|
+
await ctx.database.write(async () => {
|
|
18670
|
+
const messages = (await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf([...repairs.keys()]))).fetch()).filter(
|
|
18671
|
+
(message) => message._raw.tool_call_events === repairs.get(message.id)?.raw
|
|
18672
|
+
);
|
|
18673
|
+
if (messages.length === 0) return;
|
|
18674
|
+
const conversationIds = [...new Set(messages.map((message) => message.conversationId))];
|
|
18675
|
+
const conversations = await ctx.conversationsCollection.query(import_watermelondb2.Q.where("conversation_id", import_watermelondb2.Q.oneOf(conversationIds))).fetch();
|
|
18676
|
+
await ctx.database.batch(
|
|
18677
|
+
...messages.map(
|
|
18678
|
+
(message) => message.prepareUpdate((msg) => {
|
|
18679
|
+
msg._setRaw("tool_call_events", repairs.get(message.id).column);
|
|
18680
|
+
})
|
|
18681
|
+
),
|
|
18682
|
+
...conversations.map((conversation) => conversation.prepareUpdate(() => {
|
|
18683
|
+
}))
|
|
18684
|
+
);
|
|
18685
|
+
encrypted += messages.length;
|
|
18686
|
+
});
|
|
18687
|
+
}
|
|
18688
|
+
return encrypted;
|
|
18689
|
+
}
|
|
18690
|
+
async function savedKeyOpensExistingData(ctx, address, signMessage, embeddedWalletSigner) {
|
|
18691
|
+
const v3Probe = await findEncryptedContent(ctx, "enc:v3:%");
|
|
18692
|
+
if (v3Probe) {
|
|
18693
|
+
const { status } = await decryptFieldDetailed(v3Probe, address);
|
|
18694
|
+
if (status !== "auth_mismatch" && status !== "key_missing") return true;
|
|
18695
|
+
return refreshEncryptionKeyIfMatches(address, v3Probe, signMessage, embeddedWalletSigner);
|
|
18696
|
+
}
|
|
18697
|
+
const v2Probe = await findEncryptedContent(ctx, "enc:v2:%");
|
|
18698
|
+
if (!v2Probe) return true;
|
|
18699
|
+
return refreshEncryptionKeyIfMatches(address, v2Probe, signMessage, embeddedWalletSigner);
|
|
18700
|
+
}
|
|
18701
|
+
async function findEncryptedContent(ctx, pattern) {
|
|
18702
|
+
const [row] = await ctx.messagesCollection.query(import_watermelondb2.Q.where("content", import_watermelondb2.Q.like(pattern)), import_watermelondb2.Q.take(1)).unsafeFetchRaw();
|
|
18703
|
+
return row ? String(row.content) : null;
|
|
18704
|
+
}
|
|
18556
18705
|
async function updateMessageErrorOp(ctx, uniqueId, error) {
|
|
18557
18706
|
let message;
|
|
18558
18707
|
try {
|
|
@@ -18696,6 +18845,95 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
18696
18845
|
})
|
|
18697
18846
|
);
|
|
18698
18847
|
}
|
|
18848
|
+
var CHUNK_VECTOR_BATCH_SIZE = 50;
|
|
18849
|
+
var CHUNK_SCAN_YIELD_BUDGET_MS = 12;
|
|
18850
|
+
var hasEmbeddingSql = `(coalesce("chunks", '') != '' or coalesce("vector", '') != '')`;
|
|
18851
|
+
function toChunkCandidateKey(raw) {
|
|
18852
|
+
return {
|
|
18853
|
+
id: raw.id,
|
|
18854
|
+
conversationId: String(raw.conversation_id),
|
|
18855
|
+
version: Number(raw.updated_at) || 0,
|
|
18856
|
+
embeddingModel: raw.embedding_model ?? null
|
|
18857
|
+
};
|
|
18858
|
+
}
|
|
18859
|
+
async function fetchRowsByIds(ctx, ids) {
|
|
18860
|
+
if (ids.length === 0) return [];
|
|
18861
|
+
return await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(ids))).unsafeFetchRaw();
|
|
18862
|
+
}
|
|
18863
|
+
async function projectedChunkRowSource(ctx, filter) {
|
|
18864
|
+
const clauses = [
|
|
18865
|
+
`"history"."_status" is not 'deleted'`,
|
|
18866
|
+
hasEmbeddingSql,
|
|
18867
|
+
`exists (select 1 from "conversations" where "conversations"."conversation_id" = "history"."conversation_id" and "conversations"."is_deleted" = 0 and "conversations"."_status" is not 'deleted')`
|
|
18868
|
+
];
|
|
18869
|
+
const args = [];
|
|
18870
|
+
if (filter.conversationId !== void 0) {
|
|
18871
|
+
clauses.push(`"history"."conversation_id" = ?`);
|
|
18872
|
+
args.push(filter.conversationId);
|
|
18873
|
+
}
|
|
18874
|
+
if (filter.excludeConversationId !== void 0) {
|
|
18875
|
+
clauses.push(`"history"."conversation_id" != ?`);
|
|
18876
|
+
args.push(filter.excludeConversationId);
|
|
18877
|
+
}
|
|
18878
|
+
const keyRows = await ctx.messagesCollection.query(
|
|
18879
|
+
import_watermelondb2.Q.unsafeSqlQuery(
|
|
18880
|
+
`select "id", "conversation_id", "updated_at", "embedding_model" from "history" where ${clauses.join(" and ")}`,
|
|
18881
|
+
args
|
|
18882
|
+
)
|
|
18883
|
+
).unsafeFetchRaw();
|
|
18884
|
+
return {
|
|
18885
|
+
keys: keyRows.map(toChunkCandidateKey),
|
|
18886
|
+
loadVectorRows: async (ids) => {
|
|
18887
|
+
if (ids.length === 0) return [];
|
|
18888
|
+
return await ctx.messagesCollection.query(
|
|
18889
|
+
import_watermelondb2.Q.unsafeSqlQuery(
|
|
18890
|
+
`select "id", "updated_at", "chunks", "vector" from "history" where "_status" is not 'deleted' and "id" in (${ids.map(() => "?").join(",")})`,
|
|
18891
|
+
ids
|
|
18892
|
+
)
|
|
18893
|
+
).unsafeFetchRaw();
|
|
18894
|
+
},
|
|
18895
|
+
loadFullRows: (ids) => fetchRowsByIds(ctx, ids)
|
|
18896
|
+
};
|
|
18897
|
+
}
|
|
18898
|
+
async function fullScanChunkRowSource(ctx, filter) {
|
|
18899
|
+
const activeConversations = await ctx.conversationsCollection.query(import_watermelondb2.Q.where("is_deleted", false)).fetch();
|
|
18900
|
+
const activeConversationIds = new Set(
|
|
18901
|
+
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
18902
|
+
);
|
|
18903
|
+
const queryConditions = filter.conversationId !== void 0 ? [import_watermelondb2.Q.where("conversation_id", filter.conversationId)] : [];
|
|
18904
|
+
const rows = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
18905
|
+
const rowsById = /* @__PURE__ */ new Map();
|
|
18906
|
+
for (const row of rows) {
|
|
18907
|
+
const conversationId = String(row.conversation_id);
|
|
18908
|
+
if (!activeConversationIds.has(conversationId)) continue;
|
|
18909
|
+
if (filter.excludeConversationId !== void 0 && conversationId === filter.excludeConversationId) {
|
|
18910
|
+
continue;
|
|
18911
|
+
}
|
|
18912
|
+
if (!row.chunks && !row.vector) continue;
|
|
18913
|
+
rowsById.set(row.id, row);
|
|
18914
|
+
}
|
|
18915
|
+
const pick = (ids) => Promise.resolve(
|
|
18916
|
+
ids.flatMap((id) => {
|
|
18917
|
+
const row = rowsById.get(id);
|
|
18918
|
+
return row ? [row] : [];
|
|
18919
|
+
})
|
|
18920
|
+
);
|
|
18921
|
+
return {
|
|
18922
|
+
keys: Array.from(rowsById.values(), toChunkCandidateKey),
|
|
18923
|
+
loadVectorRows: pick,
|
|
18924
|
+
loadFullRows: pick
|
|
18925
|
+
};
|
|
18926
|
+
}
|
|
18927
|
+
async function chunkRowSource(ctx, filter) {
|
|
18928
|
+
try {
|
|
18929
|
+
return await projectedChunkRowSource(ctx, filter);
|
|
18930
|
+
} catch (err) {
|
|
18931
|
+
getLogger().debug(
|
|
18932
|
+
"searchChunksOp: projected SQL unavailable, using full-load fallback: " + (err instanceof Error ? err.message : String(err))
|
|
18933
|
+
);
|
|
18934
|
+
return fullScanChunkRowSource(ctx, filter);
|
|
18935
|
+
}
|
|
18936
|
+
}
|
|
18699
18937
|
async function searchChunksOp(ctx, queryVector, options) {
|
|
18700
18938
|
const {
|
|
18701
18939
|
limit = 10,
|
|
@@ -18703,83 +18941,111 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
18703
18941
|
conversationId,
|
|
18704
18942
|
excludeConversationId,
|
|
18705
18943
|
embeddingModel,
|
|
18706
|
-
chunkCache
|
|
18944
|
+
chunkCache,
|
|
18945
|
+
onStats
|
|
18707
18946
|
} = options || {};
|
|
18708
|
-
const
|
|
18709
|
-
const
|
|
18710
|
-
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
18711
|
-
);
|
|
18712
|
-
const queryConditions = conversationId ? [import_watermelondb2.Q.where("conversation_id", conversationId)] : [];
|
|
18713
|
-
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
18947
|
+
const source = await chunkRowSource(ctx, { conversationId, excludeConversationId });
|
|
18948
|
+
const yieldIfDue = createTimeSliceYielder(CHUNK_SCAN_YIELD_BUDGET_MS);
|
|
18714
18949
|
const candidates = [];
|
|
18715
18950
|
let staleSkipped = 0;
|
|
18716
18951
|
let unreadableVectors = 0;
|
|
18717
|
-
|
|
18718
|
-
|
|
18719
|
-
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
|
|
18726
|
-
}
|
|
18952
|
+
let cacheHits = 0;
|
|
18953
|
+
const missIds = [];
|
|
18954
|
+
const orderById = /* @__PURE__ */ new Map();
|
|
18955
|
+
for (const [order, key] of source.keys.entries()) {
|
|
18956
|
+
await yieldIfDue();
|
|
18957
|
+
orderById.set(key.id, order);
|
|
18958
|
+
if (embeddingModel && key.embeddingModel !== null && key.embeddingModel !== embeddingModel) {
|
|
18959
|
+
staleSkipped++;
|
|
18960
|
+
continue;
|
|
18727
18961
|
}
|
|
18728
|
-
const
|
|
18729
|
-
|
|
18730
|
-
|
|
18731
|
-
if (cached.chunks.length > 0) {
|
|
18732
|
-
for (let ci = 0; ci < cached.chunks.length; ci++) {
|
|
18733
|
-
const vec = cached.chunks[ci];
|
|
18734
|
-
if (vec.length === 0) continue;
|
|
18735
|
-
const similarity = cosineSimilarity(queryVector, vec);
|
|
18736
|
-
if (similarity >= minSimilarity) {
|
|
18737
|
-
candidates.push({
|
|
18738
|
-
message,
|
|
18739
|
-
similarity,
|
|
18740
|
-
chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
|
|
18741
|
-
});
|
|
18742
|
-
}
|
|
18743
|
-
}
|
|
18744
|
-
} else if (cached.fallback) {
|
|
18745
|
-
const similarity = cosineSimilarity(queryVector, cached.fallback);
|
|
18746
|
-
if (similarity >= minSimilarity) {
|
|
18747
|
-
candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
|
|
18748
|
-
}
|
|
18749
|
-
}
|
|
18962
|
+
const cached = chunkCache?.get(key.id);
|
|
18963
|
+
if (!cached || cached.version !== key.version) {
|
|
18964
|
+
missIds.push(key.id);
|
|
18750
18965
|
continue;
|
|
18751
18966
|
}
|
|
18752
|
-
|
|
18753
|
-
if (chunks
|
|
18754
|
-
|
|
18755
|
-
|
|
18756
|
-
unreadableVectors++;
|
|
18757
|
-
})
|
|
18758
|
-
);
|
|
18759
|
-
chunkCache?.set(message.id, { version, chunks: vectors });
|
|
18760
|
-
for (let ci = 0; ci < chunks.length; ci++) {
|
|
18761
|
-
const vec = vectors[ci];
|
|
18967
|
+
cacheHits++;
|
|
18968
|
+
if (cached.chunks.length > 0) {
|
|
18969
|
+
for (let ci = 0; ci < cached.chunks.length; ci++) {
|
|
18970
|
+
const vec = cached.chunks[ci];
|
|
18762
18971
|
if (vec.length === 0) continue;
|
|
18763
18972
|
const similarity = cosineSimilarity(queryVector, vec);
|
|
18764
18973
|
if (similarity >= minSimilarity) {
|
|
18765
18974
|
candidates.push({
|
|
18766
|
-
|
|
18975
|
+
id: key.id,
|
|
18976
|
+
version: key.version,
|
|
18977
|
+
order,
|
|
18767
18978
|
similarity,
|
|
18768
|
-
chunkTextSource: { kind: "chunk",
|
|
18979
|
+
chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version: key.version }
|
|
18769
18980
|
});
|
|
18770
18981
|
}
|
|
18771
18982
|
}
|
|
18772
|
-
} else {
|
|
18773
|
-
const
|
|
18774
|
-
if (!messageVector || messageVector.length === 0) continue;
|
|
18775
|
-
const fallback = Float32Array.from(messageVector);
|
|
18776
|
-
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
18777
|
-
const similarity = cosineSimilarity(queryVector, fallback);
|
|
18983
|
+
} else if (cached.fallback) {
|
|
18984
|
+
const similarity = cosineSimilarity(queryVector, cached.fallback);
|
|
18778
18985
|
if (similarity >= minSimilarity) {
|
|
18779
|
-
candidates.push({
|
|
18986
|
+
candidates.push({
|
|
18987
|
+
id: key.id,
|
|
18988
|
+
version: key.version,
|
|
18989
|
+
order,
|
|
18990
|
+
similarity,
|
|
18991
|
+
chunkTextSource: { kind: "message" }
|
|
18992
|
+
});
|
|
18993
|
+
}
|
|
18994
|
+
}
|
|
18995
|
+
}
|
|
18996
|
+
let rowsFetched = 0;
|
|
18997
|
+
for (let offset = 0; offset < missIds.length; offset += CHUNK_VECTOR_BATCH_SIZE) {
|
|
18998
|
+
const rows = await source.loadVectorRows(
|
|
18999
|
+
missIds.slice(offset, offset + CHUNK_VECTOR_BATCH_SIZE)
|
|
19000
|
+
);
|
|
19001
|
+
rowsFetched += rows.length;
|
|
19002
|
+
for (const row of rows) {
|
|
19003
|
+
await yieldIfDue();
|
|
19004
|
+
const id = row.id;
|
|
19005
|
+
const version = Number(row.updated_at) || 0;
|
|
19006
|
+
const order = orderById.get(id) ?? Number.MAX_SAFE_INTEGER;
|
|
19007
|
+
const chunks = await readRawJsonField(row, "chunks", ctx.walletAddress);
|
|
19008
|
+
if (chunks && chunks.length > 0) {
|
|
19009
|
+
const vectors = chunks.map(
|
|
19010
|
+
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
19011
|
+
unreadableVectors++;
|
|
19012
|
+
})
|
|
19013
|
+
);
|
|
19014
|
+
chunkCache?.set(id, { version, chunks: vectors });
|
|
19015
|
+
for (let ci = 0; ci < chunks.length; ci++) {
|
|
19016
|
+
const vec = vectors[ci];
|
|
19017
|
+
if (vec.length === 0) continue;
|
|
19018
|
+
const similarity = cosineSimilarity(queryVector, vec);
|
|
19019
|
+
if (similarity >= minSimilarity) {
|
|
19020
|
+
candidates.push({
|
|
19021
|
+
id,
|
|
19022
|
+
version,
|
|
19023
|
+
order,
|
|
19024
|
+
similarity,
|
|
19025
|
+
chunkTextSource: { kind: "chunk", chunk: chunks[ci], siblings: chunks }
|
|
19026
|
+
});
|
|
19027
|
+
}
|
|
19028
|
+
}
|
|
19029
|
+
} else {
|
|
19030
|
+
const messageVector = await readRawJsonField(row, "vector", ctx.walletAddress);
|
|
19031
|
+
if (messageVector && messageVector.length > 0) {
|
|
19032
|
+
const fallback = Float32Array.from(messageVector);
|
|
19033
|
+
chunkCache?.set(id, { version, chunks: [], fallback });
|
|
19034
|
+
const similarity = cosineSimilarity(queryVector, fallback);
|
|
19035
|
+
if (similarity >= minSimilarity) {
|
|
19036
|
+
candidates.push({
|
|
19037
|
+
id,
|
|
19038
|
+
version,
|
|
19039
|
+
order,
|
|
19040
|
+
similarity,
|
|
19041
|
+
chunkTextSource: { kind: "message" }
|
|
19042
|
+
});
|
|
19043
|
+
}
|
|
19044
|
+
}
|
|
18780
19045
|
}
|
|
18781
19046
|
}
|
|
18782
19047
|
}
|
|
19048
|
+
onStats?.({ rowsScanned: source.keys.length, rowsFetched, cacheHits });
|
|
18783
19049
|
if (staleSkipped > 0) {
|
|
18784
19050
|
getLogger().warn(
|
|
18785
19051
|
`searchChunksOp: skipped ${staleSkipped} messages whose embedding model differs from the current model (${embeddingModel}) \u2014 re-embed via chunkAndEmbedAllMessages`
|
|
@@ -18790,12 +19056,17 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
18790
19056
|
`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`
|
|
18791
19057
|
);
|
|
18792
19058
|
}
|
|
18793
|
-
const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
18794
|
-
const
|
|
18795
|
-
|
|
19059
|
+
const topK = candidates.sort((a, b) => b.similarity - a.similarity || a.order - b.order).slice(0, limit);
|
|
19060
|
+
const topIds = Array.from(new Set(topK.map((c) => c.id)));
|
|
19061
|
+
const fullRows = await source.loadFullRows(topIds);
|
|
19062
|
+
const rowById = new Map(fullRows.map((row) => [row.id, row]));
|
|
19063
|
+
const liveTopK = topK.filter((c) => {
|
|
19064
|
+
const row = rowById.get(c.id);
|
|
19065
|
+
return row !== void 0 && (Number(row.updated_at) || 0) === c.version;
|
|
19066
|
+
});
|
|
18796
19067
|
const storedById = new Map(
|
|
18797
19068
|
await Promise.all(
|
|
18798
|
-
Array.from(
|
|
19069
|
+
Array.from(rowById, async ([id, m]) => {
|
|
18799
19070
|
const stored = await messageRawToStored(
|
|
18800
19071
|
m,
|
|
18801
19072
|
ctx.walletAddress,
|
|
@@ -18808,24 +19079,24 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
18808
19079
|
);
|
|
18809
19080
|
const chunkStateByMsgId = /* @__PURE__ */ new Map();
|
|
18810
19081
|
const needsChunkText = /* @__PURE__ */ new Set();
|
|
18811
|
-
for (const c of
|
|
18812
|
-
if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.
|
|
19082
|
+
for (const c of liveTopK) {
|
|
19083
|
+
if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.id);
|
|
18813
19084
|
}
|
|
18814
19085
|
await Promise.all(
|
|
18815
19086
|
Array.from(needsChunkText, async (id) => {
|
|
18816
|
-
const m =
|
|
19087
|
+
const m = rowById.get(id);
|
|
18817
19088
|
const parsed = await readRawJsonField(m, "chunks", ctx.walletAddress);
|
|
18818
19089
|
const version = Number(m.updated_at) || 0;
|
|
18819
19090
|
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
18820
19091
|
})
|
|
18821
19092
|
);
|
|
18822
|
-
return
|
|
18823
|
-
const stored = { ...storedById.get(
|
|
19093
|
+
return liveTopK.map(({ id, similarity, chunkTextSource }) => {
|
|
19094
|
+
const stored = { ...storedById.get(id) };
|
|
18824
19095
|
let chunkText2;
|
|
18825
19096
|
if (chunkTextSource.kind === "chunk") {
|
|
18826
19097
|
chunkText2 = resolveChunkText(stored.content, chunkTextSource.chunk, chunkTextSource.siblings);
|
|
18827
19098
|
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
18828
|
-
const state = chunkStateByMsgId.get(
|
|
19099
|
+
const state = chunkStateByMsgId.get(id);
|
|
18829
19100
|
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
18830
19101
|
chunkText2 = resolveChunkText(stored.content, chunk, state?.chunks);
|
|
18831
19102
|
} else {
|
|
@@ -19927,13 +20198,35 @@ async function generateEmbedding(text12, options) {
|
|
|
19927
20198
|
if (total === void 0) return embedOne(text12, options, void 0);
|
|
19928
20199
|
return withDeadline((signal) => embedOne(text12, options, signal), total, "embedding");
|
|
19929
20200
|
}
|
|
20201
|
+
var inFlightByCache = /* @__PURE__ */ new WeakMap();
|
|
19930
20202
|
async function embedOne(text12, options, outer) {
|
|
19931
|
-
const {
|
|
19932
|
-
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
20203
|
+
const { cache } = options;
|
|
20204
|
+
if (!cache) return Array.from(await requestEmbedding(text12, options, outer));
|
|
20205
|
+
const cached = cache.get(text12);
|
|
20206
|
+
if (cached) return Array.from(cached);
|
|
20207
|
+
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
20208
|
+
inFlightByCache.set(cache, inFlight);
|
|
20209
|
+
const pending = inFlight.get(text12);
|
|
20210
|
+
if (pending) {
|
|
20211
|
+
try {
|
|
20212
|
+
return Array.from(await pending);
|
|
20213
|
+
} catch (err) {
|
|
20214
|
+
if (outer?.aborted) throw err;
|
|
20215
|
+
}
|
|
20216
|
+
}
|
|
20217
|
+
const request = requestEmbedding(text12, options, outer);
|
|
20218
|
+
inFlight.set(text12, request);
|
|
20219
|
+
try {
|
|
20220
|
+
const embedding = await request;
|
|
20221
|
+
cache.set(text12, embedding);
|
|
20222
|
+
return Array.from(embedding);
|
|
20223
|
+
} finally {
|
|
20224
|
+
if (inFlight.get(text12) === request) inFlight.delete(text12);
|
|
19936
20225
|
}
|
|
20226
|
+
}
|
|
20227
|
+
async function requestEmbedding(text12, options, outer) {
|
|
20228
|
+
const { baseUrl = BASE_URL, model } = options;
|
|
20229
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
19937
20230
|
const headers = {
|
|
19938
20231
|
...await resolveAuthHeaders(options, outer),
|
|
19939
20232
|
...taskTypeHeader(options.taskType)
|
|
@@ -19968,11 +20261,7 @@ async function embedOne(text12, options, outer) {
|
|
|
19968
20261
|
totalTokens: response.data.usage.total_tokens ?? 0
|
|
19969
20262
|
});
|
|
19970
20263
|
}
|
|
19971
|
-
|
|
19972
|
-
if (cache) {
|
|
19973
|
-
cache.set(text12, f32Embedding);
|
|
19974
|
-
}
|
|
19975
|
-
return Array.from(f32Embedding);
|
|
20264
|
+
return Float32Array.from(embedding);
|
|
19976
20265
|
}
|
|
19977
20266
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
19978
20267
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
@@ -30436,9 +30725,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
30436
30725
|
const updatedMs = updatedAt.getTime();
|
|
30437
30726
|
if (!Number.isFinite(updatedMs)) return noDate;
|
|
30438
30727
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
30439
|
-
const
|
|
30440
|
-
if (!Number.isFinite(
|
|
30441
|
-
const ageDays2 = Math.max(0, (
|
|
30728
|
+
const nowMs2 = now.getTime();
|
|
30729
|
+
if (!Number.isFinite(nowMs2)) return noDate;
|
|
30730
|
+
const ageDays2 = Math.max(0, (nowMs2 - updatedMs) / DAY_MS2);
|
|
30442
30731
|
const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
|
|
30443
30732
|
const floor = opts.floor ?? DEFAULT_FLOOR;
|
|
30444
30733
|
const decay = perYearDecay * (ageDays2 / 365);
|
|
@@ -30950,9 +31239,6 @@ function createVaultEmbeddingCache(maxSize = DEFAULT_VAULT_CACHE_SIZE) {
|
|
|
30950
31239
|
|
|
30951
31240
|
// src/lib/memoryVault/searchTool.ts
|
|
30952
31241
|
var DEFAULT_RERANK_TOP_N = 5;
|
|
30953
|
-
function nowMs() {
|
|
30954
|
-
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
30955
|
-
}
|
|
30956
31242
|
var warnedProgrammaticDecomposeIgnored = false;
|
|
30957
31243
|
function normalizeEventTimeKind(kind) {
|
|
30958
31244
|
return kind === "point" || kind === "range" || kind === "ongoing" ? kind : null;
|
|
@@ -33854,6 +34140,32 @@ function rankProfileCandidates(inputs, now = Date.now(), options = {}) {
|
|
|
33854
34140
|
return ranked;
|
|
33855
34141
|
}
|
|
33856
34142
|
|
|
34143
|
+
// src/lib/db/chat/embeddingCache.ts
|
|
34144
|
+
var MaskScopedEmbeddingCache = class extends Map {
|
|
34145
|
+
constructor(inner, masked) {
|
|
34146
|
+
super();
|
|
34147
|
+
this.inner = inner;
|
|
34148
|
+
this.masked = masked;
|
|
34149
|
+
}
|
|
34150
|
+
key(text12) {
|
|
34151
|
+
return `${this.masked ? "m" : "r"}:${text12}`;
|
|
34152
|
+
}
|
|
34153
|
+
get(text12) {
|
|
34154
|
+
return this.inner.get(this.key(text12));
|
|
34155
|
+
}
|
|
34156
|
+
set(text12, value) {
|
|
34157
|
+
this.inner.set(this.key(text12), value);
|
|
34158
|
+
return this;
|
|
34159
|
+
}
|
|
34160
|
+
};
|
|
34161
|
+
var scopedViews = /* @__PURE__ */ new WeakMap();
|
|
34162
|
+
function maskScopedEmbeddingCache(cache, masked) {
|
|
34163
|
+
const views = scopedViews.get(cache) ?? {};
|
|
34164
|
+
scopedViews.set(cache, views);
|
|
34165
|
+
const slot = masked ? "masked" : "raw";
|
|
34166
|
+
return views[slot] ?? (views[slot] = new MaskScopedEmbeddingCache(cache, masked));
|
|
34167
|
+
}
|
|
34168
|
+
|
|
33857
34169
|
// src/lib/memory/recall.ts
|
|
33858
34170
|
init_logger();
|
|
33859
34171
|
|
|
@@ -34064,9 +34376,6 @@ function scoreEventTimeOverlap(memoryStart, memoryEnd, memoryKind, window2) {
|
|
|
34064
34376
|
var DEFAULT_LIMIT = 8;
|
|
34065
34377
|
var DEFAULT_BUDGET = "low";
|
|
34066
34378
|
var DEFAULT_FACT_MIN_SCORE = 0.1;
|
|
34067
|
-
function nowMs2() {
|
|
34068
|
-
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
34069
|
-
}
|
|
34070
34379
|
var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
34071
34380
|
var DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS = 8e3;
|
|
34072
34381
|
function flagsForBudget(budget) {
|
|
@@ -34104,12 +34413,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
34104
34413
|
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
34105
34414
|
const embeddingOptions = {
|
|
34106
34415
|
...ctx.embeddingOptions,
|
|
34107
|
-
taskType: "memory_recall_embed"
|
|
34416
|
+
taskType: "memory_recall_embed",
|
|
34417
|
+
...options.embeddingCache && !ctx.embeddingOptions.cache && {
|
|
34418
|
+
cache: maskScopedEmbeddingCache(
|
|
34419
|
+
options.embeddingCache,
|
|
34420
|
+
Boolean(ctx.embeddingOptions.maskInput)
|
|
34421
|
+
)
|
|
34422
|
+
}
|
|
34108
34423
|
};
|
|
34109
|
-
const t0 =
|
|
34424
|
+
const t0 = nowMs();
|
|
34110
34425
|
let prepMs = 0;
|
|
34111
34426
|
let factLaneMs = 0;
|
|
34112
34427
|
let chunkLaneMs = 0;
|
|
34428
|
+
let chunkStats;
|
|
34113
34429
|
let fuseMs = 0;
|
|
34114
34430
|
const factResults = [];
|
|
34115
34431
|
const chunkResults = [];
|
|
@@ -34164,6 +34480,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
34164
34480
|
...decryptLastRan !== void 0 && { decryptLast: decryptLastRan },
|
|
34165
34481
|
...vaultRowsDecrypted !== void 0 && { vaultRowsDecrypted },
|
|
34166
34482
|
...vaultRowsEmbedded !== void 0 && { vaultRowsEmbedded },
|
|
34483
|
+
...chunkStats && {
|
|
34484
|
+
chunkRowsScanned: chunkStats.rowsScanned,
|
|
34485
|
+
chunkRowsFetched: chunkStats.rowsFetched,
|
|
34486
|
+
chunkCacheHits: chunkStats.cacheHits
|
|
34487
|
+
},
|
|
34167
34488
|
factCount: factResults.length,
|
|
34168
34489
|
chunkCount: chunkResults.length,
|
|
34169
34490
|
admittedCount: admitted.length,
|
|
@@ -34175,7 +34496,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
34175
34496
|
temporalLaneCount,
|
|
34176
34497
|
emptyReason: emptyReasonFor(admitted.length, laneRan),
|
|
34177
34498
|
timings: {
|
|
34178
|
-
total:
|
|
34499
|
+
total: nowMs() - t0,
|
|
34179
34500
|
prep: prepMs,
|
|
34180
34501
|
factLane: factLaneMs,
|
|
34181
34502
|
rerank: rerankMs,
|
|
@@ -34197,14 +34518,14 @@ async function recall(query, ctx, options = {}) {
|
|
|
34197
34518
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
34198
34519
|
const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
|
|
34199
34520
|
const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
|
|
34200
|
-
const prepStart =
|
|
34521
|
+
const prepStart = nowMs();
|
|
34201
34522
|
let sharedEmbedMs = 0;
|
|
34202
34523
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
34203
34524
|
needsChunkEmbedding ? generateEmbedding(query, {
|
|
34204
34525
|
...embeddingOptions,
|
|
34205
34526
|
totalTimeoutMs: queryEmbedTotalTimeoutMs
|
|
34206
34527
|
}).finally(() => {
|
|
34207
|
-
sharedEmbedMs =
|
|
34528
|
+
sharedEmbedMs = nowMs() - prepStart;
|
|
34208
34529
|
}).then((vec) => {
|
|
34209
34530
|
if (vec.length === 0) {
|
|
34210
34531
|
getLogger().warn(
|
|
@@ -34237,11 +34558,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
34237
34558
|
() => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
34238
34559
|
) : Promise.resolve([])
|
|
34239
34560
|
]);
|
|
34240
|
-
prepMs =
|
|
34561
|
+
prepMs = nowMs() - prepStart;
|
|
34241
34562
|
graphLaneCount = entityRanking.length;
|
|
34242
34563
|
temporalLaneCount = temporalRanking.length;
|
|
34243
34564
|
if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
|
|
34244
|
-
const factStart =
|
|
34565
|
+
const factStart = nowMs();
|
|
34245
34566
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
34246
34567
|
factFloor = vaultMinScore;
|
|
34247
34568
|
const {
|
|
@@ -34317,11 +34638,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
34317
34638
|
factLaneRankedOnCosine = factRankedOnCosine;
|
|
34318
34639
|
decryptLastRan = factDecryptLast;
|
|
34319
34640
|
vaultRowsDecrypted = factRowsDecrypted;
|
|
34320
|
-
factLaneMs =
|
|
34641
|
+
factLaneMs = nowMs() - factStart;
|
|
34321
34642
|
}
|
|
34322
34643
|
if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
|
|
34323
34644
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
34324
|
-
const chunkStart =
|
|
34645
|
+
const chunkStart = nowMs();
|
|
34325
34646
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
34326
34647
|
chunkFloor = chunkMinScore;
|
|
34327
34648
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
@@ -34332,12 +34653,15 @@ async function recall(query, ctx, options = {}) {
|
|
|
34332
34653
|
...options.excludeConversationId && {
|
|
34333
34654
|
excludeConversationId: options.excludeConversationId
|
|
34334
34655
|
},
|
|
34335
|
-
...ctx.chunkCache && { chunkCache: ctx.chunkCache }
|
|
34656
|
+
...ctx.chunkCache && { chunkCache: ctx.chunkCache },
|
|
34657
|
+
onStats: (stats) => {
|
|
34658
|
+
chunkStats = stats;
|
|
34659
|
+
}
|
|
34336
34660
|
});
|
|
34337
34661
|
chunkResults.push(...dedupeBy(results, (r) => r.chunkText.trim()));
|
|
34338
|
-
chunkLaneMs =
|
|
34662
|
+
chunkLaneMs = nowMs() - chunkStart;
|
|
34339
34663
|
}
|
|
34340
|
-
const fuseStart =
|
|
34664
|
+
const fuseStart = nowMs();
|
|
34341
34665
|
if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
|
|
34342
34666
|
const memories2 = [
|
|
34343
34667
|
...factResults.map((r) => toFactMemory(r, options.now)),
|
|
@@ -34345,7 +34669,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
34345
34669
|
];
|
|
34346
34670
|
memories2.sort((a, b) => b.score - a.score);
|
|
34347
34671
|
const candidateCount = factResults.length + chunkResults.length;
|
|
34348
|
-
fuseMs =
|
|
34672
|
+
fuseMs = nowMs() - fuseStart;
|
|
34349
34673
|
const admitted = memories2.slice(0, limit);
|
|
34350
34674
|
hitLimit = memories2.length > limit;
|
|
34351
34675
|
emitDiagnostics(candidateCount, admitted);
|
|
@@ -34409,7 +34733,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
34409
34733
|
memories = selection.out;
|
|
34410
34734
|
}
|
|
34411
34735
|
hitLimit = selection.cut;
|
|
34412
|
-
fuseMs =
|
|
34736
|
+
fuseMs = nowMs() - fuseStart;
|
|
34413
34737
|
emitDiagnostics(byId.size, memories);
|
|
34414
34738
|
return {
|
|
34415
34739
|
memories,
|
|
@@ -39427,6 +39751,7 @@ function serverPlatformStorage() {
|
|
|
39427
39751
|
encryptDataBatch,
|
|
39428
39752
|
encryptDataBytes,
|
|
39429
39753
|
encryptDataWithKey,
|
|
39754
|
+
encryptToolCallEventsOp,
|
|
39430
39755
|
estimateMessagesTokens,
|
|
39431
39756
|
estimateTokens,
|
|
39432
39757
|
exportPublicKey,
|