@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/react/index.mjs
CHANGED
|
@@ -10546,6 +10546,275 @@ async function clearConversationMemoriesOp(ctx, conversationId) {
|
|
|
10546
10546
|
});
|
|
10547
10547
|
}
|
|
10548
10548
|
|
|
10549
|
+
// src/lib/chatStore/vaultRecords.ts
|
|
10550
|
+
var PINNED_SORT_BASE = 2 ** 51;
|
|
10551
|
+
var recordBudgetBytes = 104e4;
|
|
10552
|
+
var storedDims = 1536;
|
|
10553
|
+
var acceptedDims = /* @__PURE__ */ new Set([1536, 4096]);
|
|
10554
|
+
var maxChunks = 16;
|
|
10555
|
+
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
10556
|
+
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
10557
|
+
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
10558
|
+
function plain(value) {
|
|
10559
|
+
return JSON.parse(JSON.stringify(value ?? {}));
|
|
10560
|
+
}
|
|
10561
|
+
function text4(value) {
|
|
10562
|
+
return typeof value === "string" ? value : void 0;
|
|
10563
|
+
}
|
|
10564
|
+
function number(value) {
|
|
10565
|
+
return typeof value === "number" ? value : void 0;
|
|
10566
|
+
}
|
|
10567
|
+
function conversationSortKey(data, createdAt) {
|
|
10568
|
+
const pinnedAt = number(data.pinnedAt);
|
|
10569
|
+
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
10570
|
+
return number(data.lastActivityAt) ?? createdAt;
|
|
10571
|
+
}
|
|
10572
|
+
function toConversation(record2) {
|
|
10573
|
+
const pinnedAt = number(record2.data.pinnedAt);
|
|
10574
|
+
const projectId = text4(record2.data.projectId);
|
|
10575
|
+
return {
|
|
10576
|
+
uniqueId: record2.id,
|
|
10577
|
+
conversationId: record2.id,
|
|
10578
|
+
title: text4(record2.data.title) ?? "",
|
|
10579
|
+
...projectId ? { projectId } : {},
|
|
10580
|
+
createdAt: new Date(record2.createdAt),
|
|
10581
|
+
updatedAt: new Date(record2.updatedAt),
|
|
10582
|
+
isDeleted: record2.isDeleted,
|
|
10583
|
+
pinnedAt: pinnedAt ? new Date(pinnedAt) : null
|
|
10584
|
+
};
|
|
10585
|
+
}
|
|
10586
|
+
function messageData(options) {
|
|
10587
|
+
return plain(
|
|
10588
|
+
Object.fromEntries(
|
|
10589
|
+
Object.entries(options).filter(
|
|
10590
|
+
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
10591
|
+
)
|
|
10592
|
+
)
|
|
10593
|
+
);
|
|
10594
|
+
}
|
|
10595
|
+
function toMessage(record2) {
|
|
10596
|
+
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
10597
|
+
return {
|
|
10598
|
+
...fields,
|
|
10599
|
+
uniqueId: record2.id,
|
|
10600
|
+
messageId: record2.sortKey,
|
|
10601
|
+
conversationId: record2.conversationId,
|
|
10602
|
+
createdAt: new Date(record2.createdAt),
|
|
10603
|
+
updatedAt: new Date(record2.updatedAt)
|
|
10604
|
+
};
|
|
10605
|
+
}
|
|
10606
|
+
function chunkOffsets(record2) {
|
|
10607
|
+
const offsets = record2.data.chunkOffsets;
|
|
10608
|
+
return Array.isArray(offsets) ? offsets : void 0;
|
|
10609
|
+
}
|
|
10610
|
+
function toSkeletons(records) {
|
|
10611
|
+
const roleById = new Map(records.map((r) => [r.id, text4(r.data.role)]));
|
|
10612
|
+
return records.map((r) => {
|
|
10613
|
+
const parentMessageId = text4(r.data.parentMessageId);
|
|
10614
|
+
const model = text4(r.data.model);
|
|
10615
|
+
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
10616
|
+
return {
|
|
10617
|
+
uniqueId: r.id,
|
|
10618
|
+
messageId: r.sortKey,
|
|
10619
|
+
conversationId: r.conversationId,
|
|
10620
|
+
role: text4(r.data.role) ?? "",
|
|
10621
|
+
createdAt: new Date(r.createdAt),
|
|
10622
|
+
...parentMessageId ? { parentMessageId } : {},
|
|
10623
|
+
...model ? { model } : {},
|
|
10624
|
+
...artifact ? { content: text4(r.data.content) ?? "" } : {}
|
|
10625
|
+
};
|
|
10626
|
+
});
|
|
10627
|
+
}
|
|
10628
|
+
function toSummary(record2) {
|
|
10629
|
+
return {
|
|
10630
|
+
uniqueId: record2.id,
|
|
10631
|
+
conversationId: record2.id,
|
|
10632
|
+
summary: text4(record2.data.summary) ?? "",
|
|
10633
|
+
summarizedUpTo: text4(record2.data.summarizedUpTo) ?? "",
|
|
10634
|
+
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
10635
|
+
createdAt: new Date(record2.createdAt),
|
|
10636
|
+
updatedAt: new Date(record2.updatedAt)
|
|
10637
|
+
};
|
|
10638
|
+
}
|
|
10639
|
+
function links(data) {
|
|
10640
|
+
return Array.isArray(data.links) ? data.links : [];
|
|
10641
|
+
}
|
|
10642
|
+
function applyLinkOps(data, ops) {
|
|
10643
|
+
let current = links(data);
|
|
10644
|
+
for (const op of ops) {
|
|
10645
|
+
if ("clear" in op) {
|
|
10646
|
+
current = [];
|
|
10647
|
+
continue;
|
|
10648
|
+
}
|
|
10649
|
+
const byId = new Map(current.map((l) => [l.memoryId, l]));
|
|
10650
|
+
const turn = /* @__PURE__ */ new Set();
|
|
10651
|
+
op.add.forEach((item, i) => {
|
|
10652
|
+
if (!item.memoryId || turn.has(item.memoryId)) return;
|
|
10653
|
+
turn.add(item.memoryId);
|
|
10654
|
+
const known = byId.get(item.memoryId);
|
|
10655
|
+
if (known && known.createdAt >= op.at + i) return;
|
|
10656
|
+
byId.set(item.memoryId, { memoryId: item.memoryId, score: item.score, createdAt: op.at + i });
|
|
10657
|
+
});
|
|
10658
|
+
current = [...byId.values()].sort((a, b) => a.createdAt - b.createdAt).slice(-MAX_PER_CONVERSATION);
|
|
10659
|
+
}
|
|
10660
|
+
return plain({ links: current });
|
|
10661
|
+
}
|
|
10662
|
+
function toLinks(record2) {
|
|
10663
|
+
return links(record2.data).map((l) => ({
|
|
10664
|
+
uniqueId: `${record2.id}:${l.memoryId}`,
|
|
10665
|
+
conversationId: record2.id,
|
|
10666
|
+
memoryId: l.memoryId,
|
|
10667
|
+
score: l.score,
|
|
10668
|
+
createdAt: new Date(l.createdAt)
|
|
10669
|
+
}));
|
|
10670
|
+
}
|
|
10671
|
+
function bytes(value) {
|
|
10672
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
10673
|
+
}
|
|
10674
|
+
function fitRecord(record2) {
|
|
10675
|
+
if (record2.kind !== "message" || bytes(record2) <= recordBudgetBytes) return record2;
|
|
10676
|
+
const data = { ...record2.data };
|
|
10677
|
+
const truncated = [];
|
|
10678
|
+
for (const field10 of droppable) {
|
|
10679
|
+
if (bytes({ ...record2, data }) <= recordBudgetBytes) break;
|
|
10680
|
+
if (data[field10] === void 0) continue;
|
|
10681
|
+
delete data[field10];
|
|
10682
|
+
truncated.push(field10);
|
|
10683
|
+
}
|
|
10684
|
+
const content = text4(data.content) ?? "";
|
|
10685
|
+
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
10686
|
+
if (over > 0) {
|
|
10687
|
+
const encoded = new TextEncoder().encode(content);
|
|
10688
|
+
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
10689
|
+
truncated.push("content");
|
|
10690
|
+
}
|
|
10691
|
+
return { ...record2, data: { ...data, truncated } };
|
|
10692
|
+
}
|
|
10693
|
+
function acceptedVector(vector2) {
|
|
10694
|
+
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
10695
|
+
if (!vector2.every(Number.isFinite) || !vector2.slice(0, storedDims).some((x) => x !== 0))
|
|
10696
|
+
return void 0;
|
|
10697
|
+
return [...vector2];
|
|
10698
|
+
}
|
|
10699
|
+
function normalized(vector2) {
|
|
10700
|
+
const norm = Math.hypot(...vector2) || 1;
|
|
10701
|
+
return vector2.map((x) => x / norm);
|
|
10702
|
+
}
|
|
10703
|
+
function fitChunks(chunks3) {
|
|
10704
|
+
const usable = chunks3.map((c) => ({ ...c, vector: acceptedVector(c.vector) }));
|
|
10705
|
+
if (usable.length === 0 || usable.some((c) => !c.vector)) return void 0;
|
|
10706
|
+
if (usable.length <= maxChunks) return usable;
|
|
10707
|
+
const out = [];
|
|
10708
|
+
for (let g = 0; g < maxChunks; g++) {
|
|
10709
|
+
const group = usable.slice(
|
|
10710
|
+
Math.floor(g * usable.length / maxChunks),
|
|
10711
|
+
Math.floor((g + 1) * usable.length / maxChunks)
|
|
10712
|
+
);
|
|
10713
|
+
const dims = group[0].vector.length;
|
|
10714
|
+
const mean = new Array(dims).fill(0);
|
|
10715
|
+
for (const c of group) {
|
|
10716
|
+
const unit = normalized(c.vector);
|
|
10717
|
+
for (let d = 0; d < dims; d++) mean[d] += unit[d];
|
|
10718
|
+
}
|
|
10719
|
+
out.push({
|
|
10720
|
+
vector: normalized(mean),
|
|
10721
|
+
startOffset: group[0].startOffset,
|
|
10722
|
+
endOffset: group[group.length - 1].endOffset
|
|
10723
|
+
});
|
|
10724
|
+
}
|
|
10725
|
+
return out;
|
|
10726
|
+
}
|
|
10727
|
+
|
|
10728
|
+
// src/lib/chatStore/chatImports.ts
|
|
10729
|
+
var importBatch = 100;
|
|
10730
|
+
var importChunks = 200;
|
|
10731
|
+
var importPlaintextBytes = 39e5;
|
|
10732
|
+
function ms(date10, fallback = 1) {
|
|
10733
|
+
const value = date10?.getTime();
|
|
10734
|
+
return value && Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback;
|
|
10735
|
+
}
|
|
10736
|
+
function bytes2(value) {
|
|
10737
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
10738
|
+
}
|
|
10739
|
+
function conversationRecord(conversation, messages) {
|
|
10740
|
+
const createdAt = ms(conversation.createdAt);
|
|
10741
|
+
const data = plain({
|
|
10742
|
+
title: conversation.title,
|
|
10743
|
+
projectId: conversation.projectId || void 0,
|
|
10744
|
+
pinnedAt: conversation.pinnedAt ? ms(conversation.pinnedAt) : void 0,
|
|
10745
|
+
lastActivityAt: Math.max(
|
|
10746
|
+
ms(conversation.updatedAt, createdAt),
|
|
10747
|
+
...messages.map((m) => ms(m.createdAt))
|
|
10748
|
+
)
|
|
10749
|
+
});
|
|
10750
|
+
return {
|
|
10751
|
+
record: {
|
|
10752
|
+
kind: "conversation",
|
|
10753
|
+
id: conversation.conversationId,
|
|
10754
|
+
conversationId: "",
|
|
10755
|
+
sortKey: conversationSortKey(data, createdAt),
|
|
10756
|
+
createdAt,
|
|
10757
|
+
updatedAt: ms(conversation.updatedAt, createdAt),
|
|
10758
|
+
isDeleted: false,
|
|
10759
|
+
data
|
|
10760
|
+
}
|
|
10761
|
+
};
|
|
10762
|
+
}
|
|
10763
|
+
function messageRecord(message) {
|
|
10764
|
+
const {
|
|
10765
|
+
uniqueId: _uniqueId,
|
|
10766
|
+
messageId: _messageId,
|
|
10767
|
+
createdAt: _createdAt,
|
|
10768
|
+
updatedAt: _updatedAt,
|
|
10769
|
+
decryptionStatus: _status,
|
|
10770
|
+
chunks: chunks3,
|
|
10771
|
+
vector: vector2,
|
|
10772
|
+
...fields
|
|
10773
|
+
} = message;
|
|
10774
|
+
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
10775
|
+
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
10776
|
+
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
10777
|
+
const record2 = fitRecord({
|
|
10778
|
+
kind: "message",
|
|
10779
|
+
id: message.uniqueId,
|
|
10780
|
+
conversationId: message.conversationId,
|
|
10781
|
+
sortKey: message.messageId,
|
|
10782
|
+
createdAt: ms(message.createdAt),
|
|
10783
|
+
updatedAt: ms(message.updatedAt, ms(message.createdAt)),
|
|
10784
|
+
isDeleted: false,
|
|
10785
|
+
data: {
|
|
10786
|
+
...messageData(fields),
|
|
10787
|
+
...fitted ? { chunkOffsets: fitted.map((c) => [c.startOffset, c.endOffset]) } : {}
|
|
10788
|
+
}
|
|
10789
|
+
});
|
|
10790
|
+
return {
|
|
10791
|
+
record: record2,
|
|
10792
|
+
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
10793
|
+
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
10794
|
+
};
|
|
10795
|
+
}
|
|
10796
|
+
function batches(records) {
|
|
10797
|
+
const out = [];
|
|
10798
|
+
let batch = [];
|
|
10799
|
+
let chunks3 = 0;
|
|
10800
|
+
let size = 0;
|
|
10801
|
+
for (const item of records) {
|
|
10802
|
+
const vectors = item.embeddings?.length ?? 0;
|
|
10803
|
+
const itemSize = bytes2(item.record);
|
|
10804
|
+
if (batch.length > 0 && (batch.length >= importBatch || chunks3 + vectors > importChunks || size + itemSize > importPlaintextBytes)) {
|
|
10805
|
+
out.push(batch);
|
|
10806
|
+
batch = [];
|
|
10807
|
+
chunks3 = 0;
|
|
10808
|
+
size = 0;
|
|
10809
|
+
}
|
|
10810
|
+
batch.push(item);
|
|
10811
|
+
chunks3 += vectors;
|
|
10812
|
+
size += itemSize;
|
|
10813
|
+
}
|
|
10814
|
+
if (batch.length) out.push(batch);
|
|
10815
|
+
return out;
|
|
10816
|
+
}
|
|
10817
|
+
|
|
10549
10818
|
// src/lib/db/entities/types.ts
|
|
10550
10819
|
var ENTITY_KINDS = [
|
|
10551
10820
|
"person",
|
|
@@ -11284,7 +11553,7 @@ var ChatStoreError = class extends Error {
|
|
|
11284
11553
|
var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links"]);
|
|
11285
11554
|
var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
|
|
11286
11555
|
var maxPayload = 2 * 1024 * 1024;
|
|
11287
|
-
var
|
|
11556
|
+
var storedDims2 = 1536;
|
|
11288
11557
|
var maxRequestCiphertext = 8 * 1024 * 1024;
|
|
11289
11558
|
var maxGetRefs = 50;
|
|
11290
11559
|
var maxImportRecords = 100;
|
|
@@ -11352,24 +11621,24 @@ function vector(v) {
|
|
|
11352
11621
|
for (let i = 0; i < v.length; i++) {
|
|
11353
11622
|
const x = v[i];
|
|
11354
11623
|
if (typeof x !== "number" || !Number.isFinite(x)) return false;
|
|
11355
|
-
if (i <
|
|
11624
|
+
if (i < storedDims2 && x !== 0) nonZero = true;
|
|
11356
11625
|
}
|
|
11357
11626
|
return nonZero;
|
|
11358
11627
|
}
|
|
11359
11628
|
function vectorFields(write) {
|
|
11360
11629
|
return {
|
|
11361
|
-
...write.embeddings !== void 0 ? { embeddings: write.embeddings.map((v) => v.slice(0,
|
|
11630
|
+
...write.embeddings !== void 0 ? { embeddings: write.embeddings.map((v) => v.slice(0, storedDims2)) } : {},
|
|
11362
11631
|
...write.embeddingModel !== void 0 ? { embedding_model: write.embeddingModel } : {}
|
|
11363
11632
|
};
|
|
11364
11633
|
}
|
|
11365
|
-
function
|
|
11634
|
+
function text5(value) {
|
|
11366
11635
|
return typeof value === "string";
|
|
11367
11636
|
}
|
|
11368
11637
|
function timestamp(value) {
|
|
11369
11638
|
return typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
11370
11639
|
}
|
|
11371
11640
|
function presigned(value) {
|
|
11372
|
-
if (!object(value) || !
|
|
11641
|
+
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))
|
|
11373
11642
|
invalid();
|
|
11374
11643
|
return {
|
|
11375
11644
|
url: value.url,
|
|
@@ -11379,7 +11648,7 @@ function presigned(value) {
|
|
|
11379
11648
|
};
|
|
11380
11649
|
}
|
|
11381
11650
|
function attachment(value) {
|
|
11382
|
-
if (!object(value) || !
|
|
11651
|
+
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))
|
|
11383
11652
|
invalid();
|
|
11384
11653
|
return {
|
|
11385
11654
|
id: value.attachment_id,
|
|
@@ -11392,7 +11661,7 @@ function attachment(value) {
|
|
|
11392
11661
|
};
|
|
11393
11662
|
}
|
|
11394
11663
|
function ref(value) {
|
|
11395
|
-
if (!object(value) || !
|
|
11664
|
+
if (!object(value) || !text5(value.kind) || !kinds.has(value.kind) || !id(value.id)) invalid();
|
|
11396
11665
|
return { kind: value.kind, id: value.id };
|
|
11397
11666
|
}
|
|
11398
11667
|
function sameMetadata(a, b) {
|
|
@@ -11615,7 +11884,7 @@ async function createRemoteChatStore(options) {
|
|
|
11615
11884
|
},
|
|
11616
11885
|
async account(signal) {
|
|
11617
11886
|
const value = await request("/account", {}, signal);
|
|
11618
|
-
if (!object(value) || value.account_id !== accountId || !
|
|
11887
|
+
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))
|
|
11619
11888
|
invalid();
|
|
11620
11889
|
if (value.key_id && value.key_id !== keyId)
|
|
11621
11890
|
throw new ChatStoreError("Canonical chat key does not match", 409, "key_mismatch");
|
|
@@ -11690,12 +11959,12 @@ async function createRemoteChatStore(options) {
|
|
|
11690
11959
|
},
|
|
11691
11960
|
async changes(cursor, options2) {
|
|
11692
11961
|
const limit = options2?.limit ?? 100;
|
|
11693
|
-
if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!
|
|
11962
|
+
if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text5(cursor) || cursor.length > 2048))
|
|
11694
11963
|
invalid();
|
|
11695
11964
|
const params = new URLSearchParams({ account_id: String(accountId), limit: String(limit) });
|
|
11696
11965
|
if (cursor) params.set("cursor", cursor);
|
|
11697
11966
|
const value = await request(`/changes?${params}`, {}, options2?.signal);
|
|
11698
|
-
if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !
|
|
11967
|
+
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))
|
|
11699
11968
|
invalid();
|
|
11700
11969
|
const items = [];
|
|
11701
11970
|
for (const item of value.items) items.push(await decode(item));
|
|
@@ -11712,7 +11981,7 @@ async function createRemoteChatStore(options) {
|
|
|
11712
11981
|
if (!Array.isArray(embedding2) || !embeddings({
|
|
11713
11982
|
record: { ...emptyMessage, isDeleted: false },
|
|
11714
11983
|
embeddings: [embedding2]
|
|
11715
|
-
}) || !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 && (!
|
|
11984
|
+
}) || !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))
|
|
11716
11985
|
invalid();
|
|
11717
11986
|
const value = await request(
|
|
11718
11987
|
"/search",
|
|
@@ -11720,7 +11989,7 @@ async function createRemoteChatStore(options) {
|
|
|
11720
11989
|
method: "POST",
|
|
11721
11990
|
body: JSON.stringify({
|
|
11722
11991
|
account_id: accountId,
|
|
11723
|
-
embedding: embedding2.slice(0,
|
|
11992
|
+
embedding: embedding2.slice(0, storedDims2),
|
|
11724
11993
|
limit,
|
|
11725
11994
|
...kindsFilter ? { kinds: kindsFilter } : {},
|
|
11726
11995
|
...options2?.conversationId ? { conversation_id: options2.conversationId } : {},
|
|
@@ -11824,199 +12093,13 @@ var emptyMessage = {
|
|
|
11824
12093
|
data: {}
|
|
11825
12094
|
};
|
|
11826
12095
|
|
|
11827
|
-
// src/lib/chatStore/vaultRecords.ts
|
|
11828
|
-
var PINNED_SORT_BASE = 2 ** 51;
|
|
11829
|
-
var recordBudgetBytes = 104e4;
|
|
11830
|
-
var storedDims2 = 1536;
|
|
11831
|
-
var acceptedDims = /* @__PURE__ */ new Set([1536, 4096]);
|
|
11832
|
-
var maxChunks = 16;
|
|
11833
|
-
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
11834
|
-
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
11835
|
-
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
11836
|
-
function plain(value) {
|
|
11837
|
-
return JSON.parse(JSON.stringify(value ?? {}));
|
|
11838
|
-
}
|
|
11839
|
-
function text5(value) {
|
|
11840
|
-
return typeof value === "string" ? value : void 0;
|
|
11841
|
-
}
|
|
11842
|
-
function number(value) {
|
|
11843
|
-
return typeof value === "number" ? value : void 0;
|
|
11844
|
-
}
|
|
11845
|
-
function conversationSortKey(data, createdAt) {
|
|
11846
|
-
const pinnedAt = number(data.pinnedAt);
|
|
11847
|
-
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
11848
|
-
return number(data.lastActivityAt) ?? createdAt;
|
|
11849
|
-
}
|
|
11850
|
-
function toConversation(record2) {
|
|
11851
|
-
const pinnedAt = number(record2.data.pinnedAt);
|
|
11852
|
-
const projectId = text5(record2.data.projectId);
|
|
11853
|
-
return {
|
|
11854
|
-
uniqueId: record2.id,
|
|
11855
|
-
conversationId: record2.id,
|
|
11856
|
-
title: text5(record2.data.title) ?? "",
|
|
11857
|
-
...projectId ? { projectId } : {},
|
|
11858
|
-
createdAt: new Date(record2.createdAt),
|
|
11859
|
-
updatedAt: new Date(record2.updatedAt),
|
|
11860
|
-
isDeleted: record2.isDeleted,
|
|
11861
|
-
pinnedAt: pinnedAt ? new Date(pinnedAt) : null
|
|
11862
|
-
};
|
|
11863
|
-
}
|
|
11864
|
-
function messageData(options) {
|
|
11865
|
-
return plain(
|
|
11866
|
-
Object.fromEntries(
|
|
11867
|
-
Object.entries(options).filter(
|
|
11868
|
-
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
11869
|
-
)
|
|
11870
|
-
)
|
|
11871
|
-
);
|
|
11872
|
-
}
|
|
11873
|
-
function toMessage(record2) {
|
|
11874
|
-
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
11875
|
-
return {
|
|
11876
|
-
...fields,
|
|
11877
|
-
uniqueId: record2.id,
|
|
11878
|
-
messageId: record2.sortKey,
|
|
11879
|
-
conversationId: record2.conversationId,
|
|
11880
|
-
createdAt: new Date(record2.createdAt),
|
|
11881
|
-
updatedAt: new Date(record2.updatedAt)
|
|
11882
|
-
};
|
|
11883
|
-
}
|
|
11884
|
-
function chunkOffsets(record2) {
|
|
11885
|
-
const offsets = record2.data.chunkOffsets;
|
|
11886
|
-
return Array.isArray(offsets) ? offsets : void 0;
|
|
11887
|
-
}
|
|
11888
|
-
function toSkeletons(records) {
|
|
11889
|
-
const roleById = new Map(records.map((r) => [r.id, text5(r.data.role)]));
|
|
11890
|
-
return records.map((r) => {
|
|
11891
|
-
const parentMessageId = text5(r.data.parentMessageId);
|
|
11892
|
-
const model = text5(r.data.model);
|
|
11893
|
-
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
11894
|
-
return {
|
|
11895
|
-
uniqueId: r.id,
|
|
11896
|
-
messageId: r.sortKey,
|
|
11897
|
-
conversationId: r.conversationId,
|
|
11898
|
-
role: text5(r.data.role) ?? "",
|
|
11899
|
-
createdAt: new Date(r.createdAt),
|
|
11900
|
-
...parentMessageId ? { parentMessageId } : {},
|
|
11901
|
-
...model ? { model } : {},
|
|
11902
|
-
...artifact ? { content: text5(r.data.content) ?? "" } : {}
|
|
11903
|
-
};
|
|
11904
|
-
});
|
|
11905
|
-
}
|
|
11906
|
-
function toSummary(record2) {
|
|
11907
|
-
return {
|
|
11908
|
-
uniqueId: record2.id,
|
|
11909
|
-
conversationId: record2.id,
|
|
11910
|
-
summary: text5(record2.data.summary) ?? "",
|
|
11911
|
-
summarizedUpTo: text5(record2.data.summarizedUpTo) ?? "",
|
|
11912
|
-
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
11913
|
-
createdAt: new Date(record2.createdAt),
|
|
11914
|
-
updatedAt: new Date(record2.updatedAt)
|
|
11915
|
-
};
|
|
11916
|
-
}
|
|
11917
|
-
function links(data) {
|
|
11918
|
-
return Array.isArray(data.links) ? data.links : [];
|
|
11919
|
-
}
|
|
11920
|
-
function applyLinkOps(data, ops) {
|
|
11921
|
-
let current = links(data);
|
|
11922
|
-
for (const op of ops) {
|
|
11923
|
-
if ("clear" in op) {
|
|
11924
|
-
current = [];
|
|
11925
|
-
continue;
|
|
11926
|
-
}
|
|
11927
|
-
const byId = new Map(current.map((l) => [l.memoryId, l]));
|
|
11928
|
-
const turn = /* @__PURE__ */ new Set();
|
|
11929
|
-
op.add.forEach((item, i) => {
|
|
11930
|
-
if (!item.memoryId || turn.has(item.memoryId)) return;
|
|
11931
|
-
turn.add(item.memoryId);
|
|
11932
|
-
const known = byId.get(item.memoryId);
|
|
11933
|
-
if (known && known.createdAt >= op.at + i) return;
|
|
11934
|
-
byId.set(item.memoryId, { memoryId: item.memoryId, score: item.score, createdAt: op.at + i });
|
|
11935
|
-
});
|
|
11936
|
-
current = [...byId.values()].sort((a, b) => a.createdAt - b.createdAt).slice(-MAX_PER_CONVERSATION);
|
|
11937
|
-
}
|
|
11938
|
-
return plain({ links: current });
|
|
11939
|
-
}
|
|
11940
|
-
function toLinks(record2) {
|
|
11941
|
-
return links(record2.data).map((l) => ({
|
|
11942
|
-
uniqueId: `${record2.id}:${l.memoryId}`,
|
|
11943
|
-
conversationId: record2.id,
|
|
11944
|
-
memoryId: l.memoryId,
|
|
11945
|
-
score: l.score,
|
|
11946
|
-
createdAt: new Date(l.createdAt)
|
|
11947
|
-
}));
|
|
11948
|
-
}
|
|
11949
|
-
function bytes(value) {
|
|
11950
|
-
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
11951
|
-
}
|
|
11952
|
-
function fitRecord(record2) {
|
|
11953
|
-
if (record2.kind !== "message" || bytes(record2) <= recordBudgetBytes) return record2;
|
|
11954
|
-
const data = { ...record2.data };
|
|
11955
|
-
const truncated = [];
|
|
11956
|
-
for (const field10 of droppable) {
|
|
11957
|
-
if (bytes({ ...record2, data }) <= recordBudgetBytes) break;
|
|
11958
|
-
if (data[field10] === void 0) continue;
|
|
11959
|
-
delete data[field10];
|
|
11960
|
-
truncated.push(field10);
|
|
11961
|
-
}
|
|
11962
|
-
const content = text5(data.content) ?? "";
|
|
11963
|
-
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
11964
|
-
if (over > 0) {
|
|
11965
|
-
const encoded = new TextEncoder().encode(content);
|
|
11966
|
-
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
11967
|
-
truncated.push("content");
|
|
11968
|
-
}
|
|
11969
|
-
return { ...record2, data: { ...data, truncated } };
|
|
11970
|
-
}
|
|
11971
|
-
function acceptedVector(vector2) {
|
|
11972
|
-
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
11973
|
-
if (!vector2.every(Number.isFinite) || !vector2.slice(0, storedDims2).some((x) => x !== 0))
|
|
11974
|
-
return void 0;
|
|
11975
|
-
return [...vector2];
|
|
11976
|
-
}
|
|
11977
|
-
function normalized(vector2) {
|
|
11978
|
-
const norm = Math.hypot(...vector2) || 1;
|
|
11979
|
-
return vector2.map((x) => x / norm);
|
|
11980
|
-
}
|
|
11981
|
-
function fitChunks(chunks3) {
|
|
11982
|
-
const usable = chunks3.map((c) => ({ ...c, vector: acceptedVector(c.vector) }));
|
|
11983
|
-
if (usable.length === 0 || usable.some((c) => !c.vector)) return void 0;
|
|
11984
|
-
if (usable.length <= maxChunks) return usable;
|
|
11985
|
-
const out = [];
|
|
11986
|
-
for (let g = 0; g < maxChunks; g++) {
|
|
11987
|
-
const group = usable.slice(
|
|
11988
|
-
Math.floor(g * usable.length / maxChunks),
|
|
11989
|
-
Math.floor((g + 1) * usable.length / maxChunks)
|
|
11990
|
-
);
|
|
11991
|
-
const dims = group[0].vector.length;
|
|
11992
|
-
const mean = new Array(dims).fill(0);
|
|
11993
|
-
for (const c of group) {
|
|
11994
|
-
const unit = normalized(c.vector);
|
|
11995
|
-
for (let d = 0; d < dims; d++) mean[d] += unit[d];
|
|
11996
|
-
}
|
|
11997
|
-
out.push({
|
|
11998
|
-
vector: normalized(mean),
|
|
11999
|
-
startOffset: group[0].startOffset,
|
|
12000
|
-
endOffset: group[group.length - 1].endOffset
|
|
12001
|
-
});
|
|
12002
|
-
}
|
|
12003
|
-
return out;
|
|
12004
|
-
}
|
|
12005
|
-
|
|
12006
12096
|
// src/lib/chatStore/migrateChats.ts
|
|
12007
12097
|
var maxPasses = 5;
|
|
12008
12098
|
var verifyBatch = 1e3;
|
|
12009
|
-
var importBatch = 100;
|
|
12010
|
-
var importChunks = 200;
|
|
12011
|
-
var importPlaintextBytes = 39e5;
|
|
12012
12099
|
var writeBatch = 25;
|
|
12013
12100
|
function key(record2) {
|
|
12014
12101
|
return `${record2.kind}/${record2.id}`;
|
|
12015
12102
|
}
|
|
12016
|
-
function ms(date10, fallback = 1) {
|
|
12017
|
-
const value = date10?.getTime();
|
|
12018
|
-
return value && Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback;
|
|
12019
|
-
}
|
|
12020
12103
|
function sealed(value) {
|
|
12021
12104
|
if (typeof value === "string") return isEncrypted(value);
|
|
12022
12105
|
if (Array.isArray(value)) return typeof value[0] !== "number" && value.some(sealed);
|
|
@@ -12024,42 +12107,6 @@ function sealed(value) {
|
|
|
12024
12107
|
return Object.values(value).some(sealed);
|
|
12025
12108
|
return false;
|
|
12026
12109
|
}
|
|
12027
|
-
function bytes2(value) {
|
|
12028
|
-
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
12029
|
-
}
|
|
12030
|
-
function messageRecord(message) {
|
|
12031
|
-
const {
|
|
12032
|
-
uniqueId: _uniqueId,
|
|
12033
|
-
messageId: _messageId,
|
|
12034
|
-
createdAt: _createdAt,
|
|
12035
|
-
updatedAt: _updatedAt,
|
|
12036
|
-
decryptionStatus: _status,
|
|
12037
|
-
chunks: chunks3,
|
|
12038
|
-
vector: vector2,
|
|
12039
|
-
...fields
|
|
12040
|
-
} = message;
|
|
12041
|
-
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
12042
|
-
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
12043
|
-
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
12044
|
-
const record2 = fitRecord({
|
|
12045
|
-
kind: "message",
|
|
12046
|
-
id: message.uniqueId,
|
|
12047
|
-
conversationId: message.conversationId,
|
|
12048
|
-
sortKey: message.messageId,
|
|
12049
|
-
createdAt: ms(message.createdAt),
|
|
12050
|
-
updatedAt: ms(message.updatedAt, ms(message.createdAt)),
|
|
12051
|
-
isDeleted: false,
|
|
12052
|
-
data: {
|
|
12053
|
-
...messageData(fields),
|
|
12054
|
-
...fitted ? { chunkOffsets: fitted.map((c) => [c.startOffset, c.endOffset]) } : {}
|
|
12055
|
-
}
|
|
12056
|
-
});
|
|
12057
|
-
return {
|
|
12058
|
-
record: record2,
|
|
12059
|
-
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
12060
|
-
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
12061
|
-
};
|
|
12062
|
-
}
|
|
12063
12110
|
async function readLocal(options) {
|
|
12064
12111
|
const { database } = options;
|
|
12065
12112
|
const ctx = {
|
|
@@ -12113,29 +12160,10 @@ async function readLocal(options) {
|
|
|
12113
12160
|
const messages = await getMessagesOp(ctx, conversationId);
|
|
12114
12161
|
const unreadableTitle = isEncrypted(conversation.title);
|
|
12115
12162
|
if (unreadableTitle) out.untitled++;
|
|
12116
|
-
const createdAt = ms(conversation.createdAt);
|
|
12117
|
-
const data = plain({
|
|
12118
|
-
title: unreadableTitle ? "" : conversation.title,
|
|
12119
|
-
projectId: conversation.projectId || void 0,
|
|
12120
|
-
pinnedAt: conversation.pinnedAt ? ms(conversation.pinnedAt) : void 0,
|
|
12121
|
-
lastActivityAt: Math.max(
|
|
12122
|
-
ms(conversation.updatedAt, createdAt),
|
|
12123
|
-
...messages.map((m) => ms(m.createdAt))
|
|
12124
|
-
)
|
|
12125
|
-
});
|
|
12126
12163
|
out.conversations++;
|
|
12127
|
-
out.records.push(
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
id: conversationId,
|
|
12131
|
-
conversationId: "",
|
|
12132
|
-
sortKey: conversationSortKey(data, createdAt),
|
|
12133
|
-
createdAt,
|
|
12134
|
-
updatedAt: ms(conversation.updatedAt, createdAt),
|
|
12135
|
-
isDeleted: false,
|
|
12136
|
-
data
|
|
12137
|
-
}
|
|
12138
|
-
});
|
|
12164
|
+
out.records.push(
|
|
12165
|
+
conversationRecord(unreadableTitle ? { ...conversation, title: "" } : conversation, messages)
|
|
12166
|
+
);
|
|
12139
12167
|
for (const message of messages) {
|
|
12140
12168
|
if (message.decryptionStatus || sealed(message)) {
|
|
12141
12169
|
skip("message", message.uniqueId, "unreadable");
|
|
@@ -12256,27 +12284,6 @@ async function deletedSinceUpload(store, journal, local, signal) {
|
|
|
12256
12284
|
};
|
|
12257
12285
|
});
|
|
12258
12286
|
}
|
|
12259
|
-
function batches(records) {
|
|
12260
|
-
const out = [];
|
|
12261
|
-
let batch = [];
|
|
12262
|
-
let chunks3 = 0;
|
|
12263
|
-
let size = 0;
|
|
12264
|
-
for (const item of records) {
|
|
12265
|
-
const vectors = item.embeddings?.length ?? 0;
|
|
12266
|
-
const itemSize = bytes2(item.record);
|
|
12267
|
-
if (batch.length > 0 && (batch.length >= importBatch || chunks3 + vectors > importChunks || size + itemSize > importPlaintextBytes)) {
|
|
12268
|
-
out.push(batch);
|
|
12269
|
-
batch = [];
|
|
12270
|
-
chunks3 = 0;
|
|
12271
|
-
size = 0;
|
|
12272
|
-
}
|
|
12273
|
-
batch.push(item);
|
|
12274
|
-
chunks3 += vectors;
|
|
12275
|
-
size += itemSize;
|
|
12276
|
-
}
|
|
12277
|
-
if (batch.length) out.push(batch);
|
|
12278
|
-
return out;
|
|
12279
|
-
}
|
|
12280
12287
|
function fitVectors(records, available2, unembedded) {
|
|
12281
12288
|
let total = records.reduce((sum, r) => sum + (r.embeddings?.length ?? 0), 0);
|
|
12282
12289
|
if (total <= available2) return records;
|
|
@@ -13357,6 +13364,45 @@ function createVaultChatBackend(options) {
|
|
|
13357
13364
|
},
|
|
13358
13365
|
flush,
|
|
13359
13366
|
poll,
|
|
13367
|
+
async importChats(chats) {
|
|
13368
|
+
await ready();
|
|
13369
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13370
|
+
const unique = (items) => items.filter(({ record: record2 }) => {
|
|
13371
|
+
const k = key2(record2.kind, record2.id);
|
|
13372
|
+
if (seen.has(k)) return false;
|
|
13373
|
+
seen.add(k);
|
|
13374
|
+
return true;
|
|
13375
|
+
});
|
|
13376
|
+
const valid = chats.filter((c) => validChatId(c.conversation.conversationId));
|
|
13377
|
+
const conversations = unique(
|
|
13378
|
+
valid.map((c) => conversationRecord(c.conversation, c.messages))
|
|
13379
|
+
);
|
|
13380
|
+
const messages = unique(
|
|
13381
|
+
valid.flatMap(
|
|
13382
|
+
(c) => c.messages.filter(
|
|
13383
|
+
(m) => m.conversationId === c.conversation.conversationId && validChatId(m.uniqueId) && Number.isSafeInteger(m.messageId)
|
|
13384
|
+
).map((m) => messageRecord({ ...m, vector: void 0, chunks: void 0 }))
|
|
13385
|
+
)
|
|
13386
|
+
);
|
|
13387
|
+
let conversationCount = 0;
|
|
13388
|
+
let messageCount = 0;
|
|
13389
|
+
try {
|
|
13390
|
+
for (const batch of batches(conversations))
|
|
13391
|
+
conversationCount += await store.importRecords(batch);
|
|
13392
|
+
for (const batch of batches(messages)) messageCount += await store.importRecords(batch);
|
|
13393
|
+
} finally {
|
|
13394
|
+
for (const { record: record2 } of messages) checked.delete(key2("message", record2.id));
|
|
13395
|
+
await refresh(conversations.map(({ record: record2 }) => key2("conversation", record2.id))).catch(
|
|
13396
|
+
() => void 0
|
|
13397
|
+
);
|
|
13398
|
+
for (const { record: record2 } of conversations) threads.delete(record2.id);
|
|
13399
|
+
channel?.postMessage("changed");
|
|
13400
|
+
emit({ type: "conversations", origin: "local" });
|
|
13401
|
+
for (const { record: record2 } of conversations)
|
|
13402
|
+
emit({ type: "messages", conversationId: record2.id, origin: "local" });
|
|
13403
|
+
}
|
|
13404
|
+
return { conversations: conversationCount, messages: messageCount };
|
|
13405
|
+
},
|
|
13360
13406
|
status: () => ({ pending: pending.size + inflight.size, ...stopped ? { stopped } : {} }),
|
|
13361
13407
|
close() {
|
|
13362
13408
|
closed = true;
|