@anuma/sdk 10.1.1 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +323 -277
- package/dist/expo/index.d.mts +3706 -3698
- package/dist/expo/index.d.ts +3706 -3698
- package/dist/expo/index.mjs +323 -277
- package/dist/react/index.cjs +323 -277
- package/dist/react/index.d.mts +4114 -4106
- package/dist/react/index.d.ts +4114 -4106
- package/dist/react/index.mjs +323 -277
- package/package.json +1 -1
package/dist/expo/index.mjs
CHANGED
|
@@ -9978,6 +9978,275 @@ async function clearConversationMemoriesOp(ctx, conversationId) {
|
|
|
9978
9978
|
});
|
|
9979
9979
|
}
|
|
9980
9980
|
|
|
9981
|
+
// src/lib/chatStore/vaultRecords.ts
|
|
9982
|
+
var PINNED_SORT_BASE = 2 ** 51;
|
|
9983
|
+
var recordBudgetBytes = 104e4;
|
|
9984
|
+
var storedDims = 1536;
|
|
9985
|
+
var acceptedDims = /* @__PURE__ */ new Set([1536, 4096]);
|
|
9986
|
+
var maxChunks = 16;
|
|
9987
|
+
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
9988
|
+
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
9989
|
+
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
9990
|
+
function plain(value) {
|
|
9991
|
+
return JSON.parse(JSON.stringify(value ?? {}));
|
|
9992
|
+
}
|
|
9993
|
+
function text4(value) {
|
|
9994
|
+
return typeof value === "string" ? value : void 0;
|
|
9995
|
+
}
|
|
9996
|
+
function number(value) {
|
|
9997
|
+
return typeof value === "number" ? value : void 0;
|
|
9998
|
+
}
|
|
9999
|
+
function conversationSortKey(data, createdAt) {
|
|
10000
|
+
const pinnedAt = number(data.pinnedAt);
|
|
10001
|
+
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
10002
|
+
return number(data.lastActivityAt) ?? createdAt;
|
|
10003
|
+
}
|
|
10004
|
+
function toConversation(record2) {
|
|
10005
|
+
const pinnedAt = number(record2.data.pinnedAt);
|
|
10006
|
+
const projectId = text4(record2.data.projectId);
|
|
10007
|
+
return {
|
|
10008
|
+
uniqueId: record2.id,
|
|
10009
|
+
conversationId: record2.id,
|
|
10010
|
+
title: text4(record2.data.title) ?? "",
|
|
10011
|
+
...projectId ? { projectId } : {},
|
|
10012
|
+
createdAt: new Date(record2.createdAt),
|
|
10013
|
+
updatedAt: new Date(record2.updatedAt),
|
|
10014
|
+
isDeleted: record2.isDeleted,
|
|
10015
|
+
pinnedAt: pinnedAt ? new Date(pinnedAt) : null
|
|
10016
|
+
};
|
|
10017
|
+
}
|
|
10018
|
+
function messageData(options) {
|
|
10019
|
+
return plain(
|
|
10020
|
+
Object.fromEntries(
|
|
10021
|
+
Object.entries(options).filter(
|
|
10022
|
+
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
10023
|
+
)
|
|
10024
|
+
)
|
|
10025
|
+
);
|
|
10026
|
+
}
|
|
10027
|
+
function toMessage(record2) {
|
|
10028
|
+
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
10029
|
+
return {
|
|
10030
|
+
...fields,
|
|
10031
|
+
uniqueId: record2.id,
|
|
10032
|
+
messageId: record2.sortKey,
|
|
10033
|
+
conversationId: record2.conversationId,
|
|
10034
|
+
createdAt: new Date(record2.createdAt),
|
|
10035
|
+
updatedAt: new Date(record2.updatedAt)
|
|
10036
|
+
};
|
|
10037
|
+
}
|
|
10038
|
+
function chunkOffsets(record2) {
|
|
10039
|
+
const offsets = record2.data.chunkOffsets;
|
|
10040
|
+
return Array.isArray(offsets) ? offsets : void 0;
|
|
10041
|
+
}
|
|
10042
|
+
function toSkeletons(records) {
|
|
10043
|
+
const roleById = new Map(records.map((r) => [r.id, text4(r.data.role)]));
|
|
10044
|
+
return records.map((r) => {
|
|
10045
|
+
const parentMessageId = text4(r.data.parentMessageId);
|
|
10046
|
+
const model = text4(r.data.model);
|
|
10047
|
+
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
10048
|
+
return {
|
|
10049
|
+
uniqueId: r.id,
|
|
10050
|
+
messageId: r.sortKey,
|
|
10051
|
+
conversationId: r.conversationId,
|
|
10052
|
+
role: text4(r.data.role) ?? "",
|
|
10053
|
+
createdAt: new Date(r.createdAt),
|
|
10054
|
+
...parentMessageId ? { parentMessageId } : {},
|
|
10055
|
+
...model ? { model } : {},
|
|
10056
|
+
...artifact ? { content: text4(r.data.content) ?? "" } : {}
|
|
10057
|
+
};
|
|
10058
|
+
});
|
|
10059
|
+
}
|
|
10060
|
+
function toSummary(record2) {
|
|
10061
|
+
return {
|
|
10062
|
+
uniqueId: record2.id,
|
|
10063
|
+
conversationId: record2.id,
|
|
10064
|
+
summary: text4(record2.data.summary) ?? "",
|
|
10065
|
+
summarizedUpTo: text4(record2.data.summarizedUpTo) ?? "",
|
|
10066
|
+
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
10067
|
+
createdAt: new Date(record2.createdAt),
|
|
10068
|
+
updatedAt: new Date(record2.updatedAt)
|
|
10069
|
+
};
|
|
10070
|
+
}
|
|
10071
|
+
function links(data) {
|
|
10072
|
+
return Array.isArray(data.links) ? data.links : [];
|
|
10073
|
+
}
|
|
10074
|
+
function applyLinkOps(data, ops) {
|
|
10075
|
+
let current = links(data);
|
|
10076
|
+
for (const op of ops) {
|
|
10077
|
+
if ("clear" in op) {
|
|
10078
|
+
current = [];
|
|
10079
|
+
continue;
|
|
10080
|
+
}
|
|
10081
|
+
const byId = new Map(current.map((l) => [l.memoryId, l]));
|
|
10082
|
+
const turn = /* @__PURE__ */ new Set();
|
|
10083
|
+
op.add.forEach((item, i) => {
|
|
10084
|
+
if (!item.memoryId || turn.has(item.memoryId)) return;
|
|
10085
|
+
turn.add(item.memoryId);
|
|
10086
|
+
const known = byId.get(item.memoryId);
|
|
10087
|
+
if (known && known.createdAt >= op.at + i) return;
|
|
10088
|
+
byId.set(item.memoryId, { memoryId: item.memoryId, score: item.score, createdAt: op.at + i });
|
|
10089
|
+
});
|
|
10090
|
+
current = [...byId.values()].sort((a, b) => a.createdAt - b.createdAt).slice(-MAX_PER_CONVERSATION);
|
|
10091
|
+
}
|
|
10092
|
+
return plain({ links: current });
|
|
10093
|
+
}
|
|
10094
|
+
function toLinks(record2) {
|
|
10095
|
+
return links(record2.data).map((l) => ({
|
|
10096
|
+
uniqueId: `${record2.id}:${l.memoryId}`,
|
|
10097
|
+
conversationId: record2.id,
|
|
10098
|
+
memoryId: l.memoryId,
|
|
10099
|
+
score: l.score,
|
|
10100
|
+
createdAt: new Date(l.createdAt)
|
|
10101
|
+
}));
|
|
10102
|
+
}
|
|
10103
|
+
function bytes(value) {
|
|
10104
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
10105
|
+
}
|
|
10106
|
+
function fitRecord(record2) {
|
|
10107
|
+
if (record2.kind !== "message" || bytes(record2) <= recordBudgetBytes) return record2;
|
|
10108
|
+
const data = { ...record2.data };
|
|
10109
|
+
const truncated = [];
|
|
10110
|
+
for (const field10 of droppable) {
|
|
10111
|
+
if (bytes({ ...record2, data }) <= recordBudgetBytes) break;
|
|
10112
|
+
if (data[field10] === void 0) continue;
|
|
10113
|
+
delete data[field10];
|
|
10114
|
+
truncated.push(field10);
|
|
10115
|
+
}
|
|
10116
|
+
const content = text4(data.content) ?? "";
|
|
10117
|
+
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
10118
|
+
if (over > 0) {
|
|
10119
|
+
const encoded = new TextEncoder().encode(content);
|
|
10120
|
+
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
10121
|
+
truncated.push("content");
|
|
10122
|
+
}
|
|
10123
|
+
return { ...record2, data: { ...data, truncated } };
|
|
10124
|
+
}
|
|
10125
|
+
function acceptedVector(vector2) {
|
|
10126
|
+
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
10127
|
+
if (!vector2.every(Number.isFinite) || !vector2.slice(0, storedDims).some((x) => x !== 0))
|
|
10128
|
+
return void 0;
|
|
10129
|
+
return [...vector2];
|
|
10130
|
+
}
|
|
10131
|
+
function normalized(vector2) {
|
|
10132
|
+
const norm = Math.hypot(...vector2) || 1;
|
|
10133
|
+
return vector2.map((x) => x / norm);
|
|
10134
|
+
}
|
|
10135
|
+
function fitChunks(chunks3) {
|
|
10136
|
+
const usable = chunks3.map((c) => ({ ...c, vector: acceptedVector(c.vector) }));
|
|
10137
|
+
if (usable.length === 0 || usable.some((c) => !c.vector)) return void 0;
|
|
10138
|
+
if (usable.length <= maxChunks) return usable;
|
|
10139
|
+
const out = [];
|
|
10140
|
+
for (let g = 0; g < maxChunks; g++) {
|
|
10141
|
+
const group = usable.slice(
|
|
10142
|
+
Math.floor(g * usable.length / maxChunks),
|
|
10143
|
+
Math.floor((g + 1) * usable.length / maxChunks)
|
|
10144
|
+
);
|
|
10145
|
+
const dims = group[0].vector.length;
|
|
10146
|
+
const mean = new Array(dims).fill(0);
|
|
10147
|
+
for (const c of group) {
|
|
10148
|
+
const unit = normalized(c.vector);
|
|
10149
|
+
for (let d = 0; d < dims; d++) mean[d] += unit[d];
|
|
10150
|
+
}
|
|
10151
|
+
out.push({
|
|
10152
|
+
vector: normalized(mean),
|
|
10153
|
+
startOffset: group[0].startOffset,
|
|
10154
|
+
endOffset: group[group.length - 1].endOffset
|
|
10155
|
+
});
|
|
10156
|
+
}
|
|
10157
|
+
return out;
|
|
10158
|
+
}
|
|
10159
|
+
|
|
10160
|
+
// src/lib/chatStore/chatImports.ts
|
|
10161
|
+
var importBatch = 100;
|
|
10162
|
+
var importChunks = 200;
|
|
10163
|
+
var importPlaintextBytes = 39e5;
|
|
10164
|
+
function ms(date10, fallback = 1) {
|
|
10165
|
+
const value = date10?.getTime();
|
|
10166
|
+
return value && Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback;
|
|
10167
|
+
}
|
|
10168
|
+
function bytes2(value) {
|
|
10169
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
10170
|
+
}
|
|
10171
|
+
function conversationRecord(conversation, messages) {
|
|
10172
|
+
const createdAt = ms(conversation.createdAt);
|
|
10173
|
+
const data = plain({
|
|
10174
|
+
title: conversation.title,
|
|
10175
|
+
projectId: conversation.projectId || void 0,
|
|
10176
|
+
pinnedAt: conversation.pinnedAt ? ms(conversation.pinnedAt) : void 0,
|
|
10177
|
+
lastActivityAt: Math.max(
|
|
10178
|
+
ms(conversation.updatedAt, createdAt),
|
|
10179
|
+
...messages.map((m) => ms(m.createdAt))
|
|
10180
|
+
)
|
|
10181
|
+
});
|
|
10182
|
+
return {
|
|
10183
|
+
record: {
|
|
10184
|
+
kind: "conversation",
|
|
10185
|
+
id: conversation.conversationId,
|
|
10186
|
+
conversationId: "",
|
|
10187
|
+
sortKey: conversationSortKey(data, createdAt),
|
|
10188
|
+
createdAt,
|
|
10189
|
+
updatedAt: ms(conversation.updatedAt, createdAt),
|
|
10190
|
+
isDeleted: false,
|
|
10191
|
+
data
|
|
10192
|
+
}
|
|
10193
|
+
};
|
|
10194
|
+
}
|
|
10195
|
+
function messageRecord(message) {
|
|
10196
|
+
const {
|
|
10197
|
+
uniqueId: _uniqueId,
|
|
10198
|
+
messageId: _messageId,
|
|
10199
|
+
createdAt: _createdAt,
|
|
10200
|
+
updatedAt: _updatedAt,
|
|
10201
|
+
decryptionStatus: _status,
|
|
10202
|
+
chunks: chunks3,
|
|
10203
|
+
vector: vector2,
|
|
10204
|
+
...fields
|
|
10205
|
+
} = message;
|
|
10206
|
+
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
10207
|
+
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
10208
|
+
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
10209
|
+
const record2 = fitRecord({
|
|
10210
|
+
kind: "message",
|
|
10211
|
+
id: message.uniqueId,
|
|
10212
|
+
conversationId: message.conversationId,
|
|
10213
|
+
sortKey: message.messageId,
|
|
10214
|
+
createdAt: ms(message.createdAt),
|
|
10215
|
+
updatedAt: ms(message.updatedAt, ms(message.createdAt)),
|
|
10216
|
+
isDeleted: false,
|
|
10217
|
+
data: {
|
|
10218
|
+
...messageData(fields),
|
|
10219
|
+
...fitted ? { chunkOffsets: fitted.map((c) => [c.startOffset, c.endOffset]) } : {}
|
|
10220
|
+
}
|
|
10221
|
+
});
|
|
10222
|
+
return {
|
|
10223
|
+
record: record2,
|
|
10224
|
+
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
10225
|
+
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
10226
|
+
};
|
|
10227
|
+
}
|
|
10228
|
+
function batches(records) {
|
|
10229
|
+
const out = [];
|
|
10230
|
+
let batch = [];
|
|
10231
|
+
let chunks3 = 0;
|
|
10232
|
+
let size = 0;
|
|
10233
|
+
for (const item of records) {
|
|
10234
|
+
const vectors = item.embeddings?.length ?? 0;
|
|
10235
|
+
const itemSize = bytes2(item.record);
|
|
10236
|
+
if (batch.length > 0 && (batch.length >= importBatch || chunks3 + vectors > importChunks || size + itemSize > importPlaintextBytes)) {
|
|
10237
|
+
out.push(batch);
|
|
10238
|
+
batch = [];
|
|
10239
|
+
chunks3 = 0;
|
|
10240
|
+
size = 0;
|
|
10241
|
+
}
|
|
10242
|
+
batch.push(item);
|
|
10243
|
+
chunks3 += vectors;
|
|
10244
|
+
size += itemSize;
|
|
10245
|
+
}
|
|
10246
|
+
if (batch.length) out.push(batch);
|
|
10247
|
+
return out;
|
|
10248
|
+
}
|
|
10249
|
+
|
|
9981
10250
|
// src/lib/db/entities/types.ts
|
|
9982
10251
|
var ENTITY_KINDS = [
|
|
9983
10252
|
"person",
|
|
@@ -10716,7 +10985,7 @@ var ChatStoreError = class extends Error {
|
|
|
10716
10985
|
var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links"]);
|
|
10717
10986
|
var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
|
|
10718
10987
|
var maxPayload = 2 * 1024 * 1024;
|
|
10719
|
-
var
|
|
10988
|
+
var storedDims2 = 1536;
|
|
10720
10989
|
var maxRequestCiphertext = 8 * 1024 * 1024;
|
|
10721
10990
|
var maxGetRefs = 50;
|
|
10722
10991
|
var maxImportRecords = 100;
|
|
@@ -10784,24 +11053,24 @@ function vector(v) {
|
|
|
10784
11053
|
for (let i = 0; i < v.length; i++) {
|
|
10785
11054
|
const x = v[i];
|
|
10786
11055
|
if (typeof x !== "number" || !Number.isFinite(x)) return false;
|
|
10787
|
-
if (i <
|
|
11056
|
+
if (i < storedDims2 && x !== 0) nonZero = true;
|
|
10788
11057
|
}
|
|
10789
11058
|
return nonZero;
|
|
10790
11059
|
}
|
|
10791
11060
|
function vectorFields(write) {
|
|
10792
11061
|
return {
|
|
10793
|
-
...write.embeddings !== void 0 ? { embeddings: write.embeddings.map((v) => v.slice(0,
|
|
11062
|
+
...write.embeddings !== void 0 ? { embeddings: write.embeddings.map((v) => v.slice(0, storedDims2)) } : {},
|
|
10794
11063
|
...write.embeddingModel !== void 0 ? { embedding_model: write.embeddingModel } : {}
|
|
10795
11064
|
};
|
|
10796
11065
|
}
|
|
10797
|
-
function
|
|
11066
|
+
function text5(value) {
|
|
10798
11067
|
return typeof value === "string";
|
|
10799
11068
|
}
|
|
10800
11069
|
function timestamp(value) {
|
|
10801
11070
|
return typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
10802
11071
|
}
|
|
10803
11072
|
function presigned(value) {
|
|
10804
|
-
if (!object(value) || !
|
|
11073
|
+
if (!object(value) || !text5(value.url) || !/^https:\/\//.test(value.url) || !text5(value.method) || !object(value.headers) || !Object.values(value.headers).every(text5) || !timestamp(value.expires_at))
|
|
10805
11074
|
invalid();
|
|
10806
11075
|
return {
|
|
10807
11076
|
url: value.url,
|
|
@@ -10811,7 +11080,7 @@ function presigned(value) {
|
|
|
10811
11080
|
};
|
|
10812
11081
|
}
|
|
10813
11082
|
function attachment(value) {
|
|
10814
|
-
if (!object(value) || !
|
|
11083
|
+
if (!object(value) || !text5(value.attachment_id) || !attachmentIdPattern.test(value.attachment_id) || !integer(value.size_bytes, 1) || value.state !== "pending" && value.state !== "committed" || value.owner_kind !== void 0 && value.owner_kind !== "message" && value.owner_kind !== "summary" || value.owner_id !== void 0 && !id(value.owner_id) || !timestamp(value.created_at) || value.committed_at !== void 0 && !timestamp(value.committed_at))
|
|
10815
11084
|
invalid();
|
|
10816
11085
|
return {
|
|
10817
11086
|
id: value.attachment_id,
|
|
@@ -10824,7 +11093,7 @@ function attachment(value) {
|
|
|
10824
11093
|
};
|
|
10825
11094
|
}
|
|
10826
11095
|
function ref(value) {
|
|
10827
|
-
if (!object(value) || !
|
|
11096
|
+
if (!object(value) || !text5(value.kind) || !kinds.has(value.kind) || !id(value.id)) invalid();
|
|
10828
11097
|
return { kind: value.kind, id: value.id };
|
|
10829
11098
|
}
|
|
10830
11099
|
function sameMetadata(a, b) {
|
|
@@ -11047,7 +11316,7 @@ async function createRemoteChatStore(options) {
|
|
|
11047
11316
|
},
|
|
11048
11317
|
async account(signal) {
|
|
11049
11318
|
const value = await request("/account", {}, signal);
|
|
11050
|
-
if (!object(value) || value.account_id !== accountId || !
|
|
11319
|
+
if (!object(value) || value.account_id !== accountId || !text5(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count) || value.changes_cursor !== void 0 && (!text5(value.changes_cursor) || value.changes_cursor.length > 2048))
|
|
11051
11320
|
invalid();
|
|
11052
11321
|
if (value.key_id && value.key_id !== keyId)
|
|
11053
11322
|
throw new ChatStoreError("Canonical chat key does not match", 409, "key_mismatch");
|
|
@@ -11122,12 +11391,12 @@ async function createRemoteChatStore(options) {
|
|
|
11122
11391
|
},
|
|
11123
11392
|
async changes(cursor, options2) {
|
|
11124
11393
|
const limit = options2?.limit ?? 100;
|
|
11125
|
-
if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!
|
|
11394
|
+
if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text5(cursor) || cursor.length > 2048))
|
|
11126
11395
|
invalid();
|
|
11127
11396
|
const params = new URLSearchParams({ account_id: String(accountId), limit: String(limit) });
|
|
11128
11397
|
if (cursor) params.set("cursor", cursor);
|
|
11129
11398
|
const value = await request(`/changes?${params}`, {}, options2?.signal);
|
|
11130
|
-
if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !
|
|
11399
|
+
if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !text5(value.next_cursor) || value.changes_cursor !== void 0 && !text5(value.changes_cursor))
|
|
11131
11400
|
invalid();
|
|
11132
11401
|
const items = [];
|
|
11133
11402
|
for (const item of value.items) items.push(await decode(item));
|
|
@@ -11144,7 +11413,7 @@ async function createRemoteChatStore(options) {
|
|
|
11144
11413
|
if (!Array.isArray(embedding2) || !embeddings({
|
|
11145
11414
|
record: { ...emptyMessage, isDeleted: false },
|
|
11146
11415
|
embeddings: [embedding2]
|
|
11147
|
-
}) || !integer(limit, 1) || limit > 50 || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || kindsFilter.some((k) => k !== "message" && k !== "summary")) || options2?.conversationId !== void 0 && !id(options2.conversationId) || options2?.excludeConversationId !== void 0 && !id(options2.excludeConversationId) || options2?.embeddingModel !== void 0 && (!
|
|
11416
|
+
}) || !integer(limit, 1) || limit > 50 || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || kindsFilter.some((k) => k !== "message" && k !== "summary")) || options2?.conversationId !== void 0 && !id(options2.conversationId) || options2?.excludeConversationId !== void 0 && !id(options2.excludeConversationId) || options2?.embeddingModel !== void 0 && (!text5(options2.embeddingModel) || options2.embeddingModel.length > 256))
|
|
11148
11417
|
invalid();
|
|
11149
11418
|
const value = await request(
|
|
11150
11419
|
"/search",
|
|
@@ -11152,7 +11421,7 @@ async function createRemoteChatStore(options) {
|
|
|
11152
11421
|
method: "POST",
|
|
11153
11422
|
body: JSON.stringify({
|
|
11154
11423
|
account_id: accountId,
|
|
11155
|
-
embedding: embedding2.slice(0,
|
|
11424
|
+
embedding: embedding2.slice(0, storedDims2),
|
|
11156
11425
|
limit,
|
|
11157
11426
|
...kindsFilter ? { kinds: kindsFilter } : {},
|
|
11158
11427
|
...options2?.conversationId ? { conversation_id: options2.conversationId } : {},
|
|
@@ -11256,199 +11525,13 @@ var emptyMessage = {
|
|
|
11256
11525
|
data: {}
|
|
11257
11526
|
};
|
|
11258
11527
|
|
|
11259
|
-
// src/lib/chatStore/vaultRecords.ts
|
|
11260
|
-
var PINNED_SORT_BASE = 2 ** 51;
|
|
11261
|
-
var recordBudgetBytes = 104e4;
|
|
11262
|
-
var storedDims2 = 1536;
|
|
11263
|
-
var acceptedDims = /* @__PURE__ */ new Set([1536, 4096]);
|
|
11264
|
-
var maxChunks = 16;
|
|
11265
|
-
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
11266
|
-
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
11267
|
-
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
11268
|
-
function plain(value) {
|
|
11269
|
-
return JSON.parse(JSON.stringify(value ?? {}));
|
|
11270
|
-
}
|
|
11271
|
-
function text5(value) {
|
|
11272
|
-
return typeof value === "string" ? value : void 0;
|
|
11273
|
-
}
|
|
11274
|
-
function number(value) {
|
|
11275
|
-
return typeof value === "number" ? value : void 0;
|
|
11276
|
-
}
|
|
11277
|
-
function conversationSortKey(data, createdAt) {
|
|
11278
|
-
const pinnedAt = number(data.pinnedAt);
|
|
11279
|
-
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
11280
|
-
return number(data.lastActivityAt) ?? createdAt;
|
|
11281
|
-
}
|
|
11282
|
-
function toConversation(record2) {
|
|
11283
|
-
const pinnedAt = number(record2.data.pinnedAt);
|
|
11284
|
-
const projectId = text5(record2.data.projectId);
|
|
11285
|
-
return {
|
|
11286
|
-
uniqueId: record2.id,
|
|
11287
|
-
conversationId: record2.id,
|
|
11288
|
-
title: text5(record2.data.title) ?? "",
|
|
11289
|
-
...projectId ? { projectId } : {},
|
|
11290
|
-
createdAt: new Date(record2.createdAt),
|
|
11291
|
-
updatedAt: new Date(record2.updatedAt),
|
|
11292
|
-
isDeleted: record2.isDeleted,
|
|
11293
|
-
pinnedAt: pinnedAt ? new Date(pinnedAt) : null
|
|
11294
|
-
};
|
|
11295
|
-
}
|
|
11296
|
-
function messageData(options) {
|
|
11297
|
-
return plain(
|
|
11298
|
-
Object.fromEntries(
|
|
11299
|
-
Object.entries(options).filter(
|
|
11300
|
-
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
11301
|
-
)
|
|
11302
|
-
)
|
|
11303
|
-
);
|
|
11304
|
-
}
|
|
11305
|
-
function toMessage(record2) {
|
|
11306
|
-
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
11307
|
-
return {
|
|
11308
|
-
...fields,
|
|
11309
|
-
uniqueId: record2.id,
|
|
11310
|
-
messageId: record2.sortKey,
|
|
11311
|
-
conversationId: record2.conversationId,
|
|
11312
|
-
createdAt: new Date(record2.createdAt),
|
|
11313
|
-
updatedAt: new Date(record2.updatedAt)
|
|
11314
|
-
};
|
|
11315
|
-
}
|
|
11316
|
-
function chunkOffsets(record2) {
|
|
11317
|
-
const offsets = record2.data.chunkOffsets;
|
|
11318
|
-
return Array.isArray(offsets) ? offsets : void 0;
|
|
11319
|
-
}
|
|
11320
|
-
function toSkeletons(records) {
|
|
11321
|
-
const roleById = new Map(records.map((r) => [r.id, text5(r.data.role)]));
|
|
11322
|
-
return records.map((r) => {
|
|
11323
|
-
const parentMessageId = text5(r.data.parentMessageId);
|
|
11324
|
-
const model = text5(r.data.model);
|
|
11325
|
-
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
11326
|
-
return {
|
|
11327
|
-
uniqueId: r.id,
|
|
11328
|
-
messageId: r.sortKey,
|
|
11329
|
-
conversationId: r.conversationId,
|
|
11330
|
-
role: text5(r.data.role) ?? "",
|
|
11331
|
-
createdAt: new Date(r.createdAt),
|
|
11332
|
-
...parentMessageId ? { parentMessageId } : {},
|
|
11333
|
-
...model ? { model } : {},
|
|
11334
|
-
...artifact ? { content: text5(r.data.content) ?? "" } : {}
|
|
11335
|
-
};
|
|
11336
|
-
});
|
|
11337
|
-
}
|
|
11338
|
-
function toSummary(record2) {
|
|
11339
|
-
return {
|
|
11340
|
-
uniqueId: record2.id,
|
|
11341
|
-
conversationId: record2.id,
|
|
11342
|
-
summary: text5(record2.data.summary) ?? "",
|
|
11343
|
-
summarizedUpTo: text5(record2.data.summarizedUpTo) ?? "",
|
|
11344
|
-
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
11345
|
-
createdAt: new Date(record2.createdAt),
|
|
11346
|
-
updatedAt: new Date(record2.updatedAt)
|
|
11347
|
-
};
|
|
11348
|
-
}
|
|
11349
|
-
function links(data) {
|
|
11350
|
-
return Array.isArray(data.links) ? data.links : [];
|
|
11351
|
-
}
|
|
11352
|
-
function applyLinkOps(data, ops) {
|
|
11353
|
-
let current = links(data);
|
|
11354
|
-
for (const op of ops) {
|
|
11355
|
-
if ("clear" in op) {
|
|
11356
|
-
current = [];
|
|
11357
|
-
continue;
|
|
11358
|
-
}
|
|
11359
|
-
const byId = new Map(current.map((l) => [l.memoryId, l]));
|
|
11360
|
-
const turn = /* @__PURE__ */ new Set();
|
|
11361
|
-
op.add.forEach((item, i) => {
|
|
11362
|
-
if (!item.memoryId || turn.has(item.memoryId)) return;
|
|
11363
|
-
turn.add(item.memoryId);
|
|
11364
|
-
const known = byId.get(item.memoryId);
|
|
11365
|
-
if (known && known.createdAt >= op.at + i) return;
|
|
11366
|
-
byId.set(item.memoryId, { memoryId: item.memoryId, score: item.score, createdAt: op.at + i });
|
|
11367
|
-
});
|
|
11368
|
-
current = [...byId.values()].sort((a, b) => a.createdAt - b.createdAt).slice(-MAX_PER_CONVERSATION);
|
|
11369
|
-
}
|
|
11370
|
-
return plain({ links: current });
|
|
11371
|
-
}
|
|
11372
|
-
function toLinks(record2) {
|
|
11373
|
-
return links(record2.data).map((l) => ({
|
|
11374
|
-
uniqueId: `${record2.id}:${l.memoryId}`,
|
|
11375
|
-
conversationId: record2.id,
|
|
11376
|
-
memoryId: l.memoryId,
|
|
11377
|
-
score: l.score,
|
|
11378
|
-
createdAt: new Date(l.createdAt)
|
|
11379
|
-
}));
|
|
11380
|
-
}
|
|
11381
|
-
function bytes(value) {
|
|
11382
|
-
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
11383
|
-
}
|
|
11384
|
-
function fitRecord(record2) {
|
|
11385
|
-
if (record2.kind !== "message" || bytes(record2) <= recordBudgetBytes) return record2;
|
|
11386
|
-
const data = { ...record2.data };
|
|
11387
|
-
const truncated = [];
|
|
11388
|
-
for (const field10 of droppable) {
|
|
11389
|
-
if (bytes({ ...record2, data }) <= recordBudgetBytes) break;
|
|
11390
|
-
if (data[field10] === void 0) continue;
|
|
11391
|
-
delete data[field10];
|
|
11392
|
-
truncated.push(field10);
|
|
11393
|
-
}
|
|
11394
|
-
const content = text5(data.content) ?? "";
|
|
11395
|
-
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
11396
|
-
if (over > 0) {
|
|
11397
|
-
const encoded = new TextEncoder().encode(content);
|
|
11398
|
-
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
11399
|
-
truncated.push("content");
|
|
11400
|
-
}
|
|
11401
|
-
return { ...record2, data: { ...data, truncated } };
|
|
11402
|
-
}
|
|
11403
|
-
function acceptedVector(vector2) {
|
|
11404
|
-
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
11405
|
-
if (!vector2.every(Number.isFinite) || !vector2.slice(0, storedDims2).some((x) => x !== 0))
|
|
11406
|
-
return void 0;
|
|
11407
|
-
return [...vector2];
|
|
11408
|
-
}
|
|
11409
|
-
function normalized(vector2) {
|
|
11410
|
-
const norm = Math.hypot(...vector2) || 1;
|
|
11411
|
-
return vector2.map((x) => x / norm);
|
|
11412
|
-
}
|
|
11413
|
-
function fitChunks(chunks3) {
|
|
11414
|
-
const usable = chunks3.map((c) => ({ ...c, vector: acceptedVector(c.vector) }));
|
|
11415
|
-
if (usable.length === 0 || usable.some((c) => !c.vector)) return void 0;
|
|
11416
|
-
if (usable.length <= maxChunks) return usable;
|
|
11417
|
-
const out = [];
|
|
11418
|
-
for (let g = 0; g < maxChunks; g++) {
|
|
11419
|
-
const group = usable.slice(
|
|
11420
|
-
Math.floor(g * usable.length / maxChunks),
|
|
11421
|
-
Math.floor((g + 1) * usable.length / maxChunks)
|
|
11422
|
-
);
|
|
11423
|
-
const dims = group[0].vector.length;
|
|
11424
|
-
const mean = new Array(dims).fill(0);
|
|
11425
|
-
for (const c of group) {
|
|
11426
|
-
const unit = normalized(c.vector);
|
|
11427
|
-
for (let d = 0; d < dims; d++) mean[d] += unit[d];
|
|
11428
|
-
}
|
|
11429
|
-
out.push({
|
|
11430
|
-
vector: normalized(mean),
|
|
11431
|
-
startOffset: group[0].startOffset,
|
|
11432
|
-
endOffset: group[group.length - 1].endOffset
|
|
11433
|
-
});
|
|
11434
|
-
}
|
|
11435
|
-
return out;
|
|
11436
|
-
}
|
|
11437
|
-
|
|
11438
11528
|
// src/lib/chatStore/migrateChats.ts
|
|
11439
11529
|
var maxPasses = 5;
|
|
11440
11530
|
var verifyBatch = 1e3;
|
|
11441
|
-
var importBatch = 100;
|
|
11442
|
-
var importChunks = 200;
|
|
11443
|
-
var importPlaintextBytes = 39e5;
|
|
11444
11531
|
var writeBatch = 25;
|
|
11445
11532
|
function key(record2) {
|
|
11446
11533
|
return `${record2.kind}/${record2.id}`;
|
|
11447
11534
|
}
|
|
11448
|
-
function ms(date10, fallback = 1) {
|
|
11449
|
-
const value = date10?.getTime();
|
|
11450
|
-
return value && Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback;
|
|
11451
|
-
}
|
|
11452
11535
|
function sealed(value) {
|
|
11453
11536
|
if (typeof value === "string") return isEncrypted(value);
|
|
11454
11537
|
if (Array.isArray(value)) return typeof value[0] !== "number" && value.some(sealed);
|
|
@@ -11456,42 +11539,6 @@ function sealed(value) {
|
|
|
11456
11539
|
return Object.values(value).some(sealed);
|
|
11457
11540
|
return false;
|
|
11458
11541
|
}
|
|
11459
|
-
function bytes2(value) {
|
|
11460
|
-
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
11461
|
-
}
|
|
11462
|
-
function messageRecord(message) {
|
|
11463
|
-
const {
|
|
11464
|
-
uniqueId: _uniqueId,
|
|
11465
|
-
messageId: _messageId,
|
|
11466
|
-
createdAt: _createdAt,
|
|
11467
|
-
updatedAt: _updatedAt,
|
|
11468
|
-
decryptionStatus: _status,
|
|
11469
|
-
chunks: chunks3,
|
|
11470
|
-
vector: vector2,
|
|
11471
|
-
...fields
|
|
11472
|
-
} = message;
|
|
11473
|
-
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
11474
|
-
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
11475
|
-
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
11476
|
-
const record2 = fitRecord({
|
|
11477
|
-
kind: "message",
|
|
11478
|
-
id: message.uniqueId,
|
|
11479
|
-
conversationId: message.conversationId,
|
|
11480
|
-
sortKey: message.messageId,
|
|
11481
|
-
createdAt: ms(message.createdAt),
|
|
11482
|
-
updatedAt: ms(message.updatedAt, ms(message.createdAt)),
|
|
11483
|
-
isDeleted: false,
|
|
11484
|
-
data: {
|
|
11485
|
-
...messageData(fields),
|
|
11486
|
-
...fitted ? { chunkOffsets: fitted.map((c) => [c.startOffset, c.endOffset]) } : {}
|
|
11487
|
-
}
|
|
11488
|
-
});
|
|
11489
|
-
return {
|
|
11490
|
-
record: record2,
|
|
11491
|
-
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
11492
|
-
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
11493
|
-
};
|
|
11494
|
-
}
|
|
11495
11542
|
async function readLocal(options) {
|
|
11496
11543
|
const { database } = options;
|
|
11497
11544
|
const ctx = {
|
|
@@ -11545,29 +11592,10 @@ async function readLocal(options) {
|
|
|
11545
11592
|
const messages = await getMessagesOp(ctx, conversationId);
|
|
11546
11593
|
const unreadableTitle = isEncrypted(conversation.title);
|
|
11547
11594
|
if (unreadableTitle) out.untitled++;
|
|
11548
|
-
const createdAt = ms(conversation.createdAt);
|
|
11549
|
-
const data = plain({
|
|
11550
|
-
title: unreadableTitle ? "" : conversation.title,
|
|
11551
|
-
projectId: conversation.projectId || void 0,
|
|
11552
|
-
pinnedAt: conversation.pinnedAt ? ms(conversation.pinnedAt) : void 0,
|
|
11553
|
-
lastActivityAt: Math.max(
|
|
11554
|
-
ms(conversation.updatedAt, createdAt),
|
|
11555
|
-
...messages.map((m) => ms(m.createdAt))
|
|
11556
|
-
)
|
|
11557
|
-
});
|
|
11558
11595
|
out.conversations++;
|
|
11559
|
-
out.records.push(
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
id: conversationId,
|
|
11563
|
-
conversationId: "",
|
|
11564
|
-
sortKey: conversationSortKey(data, createdAt),
|
|
11565
|
-
createdAt,
|
|
11566
|
-
updatedAt: ms(conversation.updatedAt, createdAt),
|
|
11567
|
-
isDeleted: false,
|
|
11568
|
-
data
|
|
11569
|
-
}
|
|
11570
|
-
});
|
|
11596
|
+
out.records.push(
|
|
11597
|
+
conversationRecord(unreadableTitle ? { ...conversation, title: "" } : conversation, messages)
|
|
11598
|
+
);
|
|
11571
11599
|
for (const message of messages) {
|
|
11572
11600
|
if (message.decryptionStatus || sealed(message)) {
|
|
11573
11601
|
skip("message", message.uniqueId, "unreadable");
|
|
@@ -11688,27 +11716,6 @@ async function deletedSinceUpload(store, journal, local, signal) {
|
|
|
11688
11716
|
};
|
|
11689
11717
|
});
|
|
11690
11718
|
}
|
|
11691
|
-
function batches(records) {
|
|
11692
|
-
const out = [];
|
|
11693
|
-
let batch = [];
|
|
11694
|
-
let chunks3 = 0;
|
|
11695
|
-
let size = 0;
|
|
11696
|
-
for (const item of records) {
|
|
11697
|
-
const vectors = item.embeddings?.length ?? 0;
|
|
11698
|
-
const itemSize = bytes2(item.record);
|
|
11699
|
-
if (batch.length > 0 && (batch.length >= importBatch || chunks3 + vectors > importChunks || size + itemSize > importPlaintextBytes)) {
|
|
11700
|
-
out.push(batch);
|
|
11701
|
-
batch = [];
|
|
11702
|
-
chunks3 = 0;
|
|
11703
|
-
size = 0;
|
|
11704
|
-
}
|
|
11705
|
-
batch.push(item);
|
|
11706
|
-
chunks3 += vectors;
|
|
11707
|
-
size += itemSize;
|
|
11708
|
-
}
|
|
11709
|
-
if (batch.length) out.push(batch);
|
|
11710
|
-
return out;
|
|
11711
|
-
}
|
|
11712
11719
|
function fitVectors(records, available2, unembedded) {
|
|
11713
11720
|
let total = records.reduce((sum, r) => sum + (r.embeddings?.length ?? 0), 0);
|
|
11714
11721
|
if (total <= available2) return records;
|
|
@@ -12789,6 +12796,45 @@ function createVaultChatBackend(options) {
|
|
|
12789
12796
|
},
|
|
12790
12797
|
flush,
|
|
12791
12798
|
poll,
|
|
12799
|
+
async importChats(chats) {
|
|
12800
|
+
await ready();
|
|
12801
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12802
|
+
const unique = (items) => items.filter(({ record: record2 }) => {
|
|
12803
|
+
const k = key2(record2.kind, record2.id);
|
|
12804
|
+
if (seen.has(k)) return false;
|
|
12805
|
+
seen.add(k);
|
|
12806
|
+
return true;
|
|
12807
|
+
});
|
|
12808
|
+
const valid = chats.filter((c) => validChatId(c.conversation.conversationId));
|
|
12809
|
+
const conversations = unique(
|
|
12810
|
+
valid.map((c) => conversationRecord(c.conversation, c.messages))
|
|
12811
|
+
);
|
|
12812
|
+
const messages = unique(
|
|
12813
|
+
valid.flatMap(
|
|
12814
|
+
(c) => c.messages.filter(
|
|
12815
|
+
(m) => m.conversationId === c.conversation.conversationId && validChatId(m.uniqueId) && Number.isSafeInteger(m.messageId)
|
|
12816
|
+
).map((m) => messageRecord({ ...m, vector: void 0, chunks: void 0 }))
|
|
12817
|
+
)
|
|
12818
|
+
);
|
|
12819
|
+
let conversationCount = 0;
|
|
12820
|
+
let messageCount = 0;
|
|
12821
|
+
try {
|
|
12822
|
+
for (const batch of batches(conversations))
|
|
12823
|
+
conversationCount += await store.importRecords(batch);
|
|
12824
|
+
for (const batch of batches(messages)) messageCount += await store.importRecords(batch);
|
|
12825
|
+
} finally {
|
|
12826
|
+
for (const { record: record2 } of messages) checked.delete(key2("message", record2.id));
|
|
12827
|
+
await refresh(conversations.map(({ record: record2 }) => key2("conversation", record2.id))).catch(
|
|
12828
|
+
() => void 0
|
|
12829
|
+
);
|
|
12830
|
+
for (const { record: record2 } of conversations) threads.delete(record2.id);
|
|
12831
|
+
channel?.postMessage("changed");
|
|
12832
|
+
emit({ type: "conversations", origin: "local" });
|
|
12833
|
+
for (const { record: record2 } of conversations)
|
|
12834
|
+
emit({ type: "messages", conversationId: record2.id, origin: "local" });
|
|
12835
|
+
}
|
|
12836
|
+
return { conversations: conversationCount, messages: messageCount };
|
|
12837
|
+
},
|
|
12792
12838
|
status: () => ({ pending: pending.size + inflight.size, ...stopped ? { stopped } : {} }),
|
|
12793
12839
|
close() {
|
|
12794
12840
|
closed = true;
|