@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.cjs
CHANGED
|
@@ -11633,6 +11633,275 @@ async function clearConversationMemoriesOp(ctx, conversationId) {
|
|
|
11633
11633
|
});
|
|
11634
11634
|
}
|
|
11635
11635
|
|
|
11636
|
+
// src/lib/chatStore/vaultRecords.ts
|
|
11637
|
+
var PINNED_SORT_BASE = 2 ** 51;
|
|
11638
|
+
var recordBudgetBytes = 104e4;
|
|
11639
|
+
var storedDims = 1536;
|
|
11640
|
+
var acceptedDims = /* @__PURE__ */ new Set([1536, 4096]);
|
|
11641
|
+
var maxChunks = 16;
|
|
11642
|
+
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
11643
|
+
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
11644
|
+
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
11645
|
+
function plain(value) {
|
|
11646
|
+
return JSON.parse(JSON.stringify(value ?? {}));
|
|
11647
|
+
}
|
|
11648
|
+
function text4(value) {
|
|
11649
|
+
return typeof value === "string" ? value : void 0;
|
|
11650
|
+
}
|
|
11651
|
+
function number(value) {
|
|
11652
|
+
return typeof value === "number" ? value : void 0;
|
|
11653
|
+
}
|
|
11654
|
+
function conversationSortKey(data, createdAt) {
|
|
11655
|
+
const pinnedAt = number(data.pinnedAt);
|
|
11656
|
+
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
11657
|
+
return number(data.lastActivityAt) ?? createdAt;
|
|
11658
|
+
}
|
|
11659
|
+
function toConversation(record2) {
|
|
11660
|
+
const pinnedAt = number(record2.data.pinnedAt);
|
|
11661
|
+
const projectId = text4(record2.data.projectId);
|
|
11662
|
+
return {
|
|
11663
|
+
uniqueId: record2.id,
|
|
11664
|
+
conversationId: record2.id,
|
|
11665
|
+
title: text4(record2.data.title) ?? "",
|
|
11666
|
+
...projectId ? { projectId } : {},
|
|
11667
|
+
createdAt: new Date(record2.createdAt),
|
|
11668
|
+
updatedAt: new Date(record2.updatedAt),
|
|
11669
|
+
isDeleted: record2.isDeleted,
|
|
11670
|
+
pinnedAt: pinnedAt ? new Date(pinnedAt) : null
|
|
11671
|
+
};
|
|
11672
|
+
}
|
|
11673
|
+
function messageData(options) {
|
|
11674
|
+
return plain(
|
|
11675
|
+
Object.fromEntries(
|
|
11676
|
+
Object.entries(options).filter(
|
|
11677
|
+
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
11678
|
+
)
|
|
11679
|
+
)
|
|
11680
|
+
);
|
|
11681
|
+
}
|
|
11682
|
+
function toMessage(record2) {
|
|
11683
|
+
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
11684
|
+
return {
|
|
11685
|
+
...fields,
|
|
11686
|
+
uniqueId: record2.id,
|
|
11687
|
+
messageId: record2.sortKey,
|
|
11688
|
+
conversationId: record2.conversationId,
|
|
11689
|
+
createdAt: new Date(record2.createdAt),
|
|
11690
|
+
updatedAt: new Date(record2.updatedAt)
|
|
11691
|
+
};
|
|
11692
|
+
}
|
|
11693
|
+
function chunkOffsets(record2) {
|
|
11694
|
+
const offsets = record2.data.chunkOffsets;
|
|
11695
|
+
return Array.isArray(offsets) ? offsets : void 0;
|
|
11696
|
+
}
|
|
11697
|
+
function toSkeletons(records) {
|
|
11698
|
+
const roleById = new Map(records.map((r) => [r.id, text4(r.data.role)]));
|
|
11699
|
+
return records.map((r) => {
|
|
11700
|
+
const parentMessageId = text4(r.data.parentMessageId);
|
|
11701
|
+
const model = text4(r.data.model);
|
|
11702
|
+
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
11703
|
+
return {
|
|
11704
|
+
uniqueId: r.id,
|
|
11705
|
+
messageId: r.sortKey,
|
|
11706
|
+
conversationId: r.conversationId,
|
|
11707
|
+
role: text4(r.data.role) ?? "",
|
|
11708
|
+
createdAt: new Date(r.createdAt),
|
|
11709
|
+
...parentMessageId ? { parentMessageId } : {},
|
|
11710
|
+
...model ? { model } : {},
|
|
11711
|
+
...artifact ? { content: text4(r.data.content) ?? "" } : {}
|
|
11712
|
+
};
|
|
11713
|
+
});
|
|
11714
|
+
}
|
|
11715
|
+
function toSummary(record2) {
|
|
11716
|
+
return {
|
|
11717
|
+
uniqueId: record2.id,
|
|
11718
|
+
conversationId: record2.id,
|
|
11719
|
+
summary: text4(record2.data.summary) ?? "",
|
|
11720
|
+
summarizedUpTo: text4(record2.data.summarizedUpTo) ?? "",
|
|
11721
|
+
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
11722
|
+
createdAt: new Date(record2.createdAt),
|
|
11723
|
+
updatedAt: new Date(record2.updatedAt)
|
|
11724
|
+
};
|
|
11725
|
+
}
|
|
11726
|
+
function links(data) {
|
|
11727
|
+
return Array.isArray(data.links) ? data.links : [];
|
|
11728
|
+
}
|
|
11729
|
+
function applyLinkOps(data, ops) {
|
|
11730
|
+
let current = links(data);
|
|
11731
|
+
for (const op of ops) {
|
|
11732
|
+
if ("clear" in op) {
|
|
11733
|
+
current = [];
|
|
11734
|
+
continue;
|
|
11735
|
+
}
|
|
11736
|
+
const byId = new Map(current.map((l) => [l.memoryId, l]));
|
|
11737
|
+
const turn = /* @__PURE__ */ new Set();
|
|
11738
|
+
op.add.forEach((item, i) => {
|
|
11739
|
+
if (!item.memoryId || turn.has(item.memoryId)) return;
|
|
11740
|
+
turn.add(item.memoryId);
|
|
11741
|
+
const known = byId.get(item.memoryId);
|
|
11742
|
+
if (known && known.createdAt >= op.at + i) return;
|
|
11743
|
+
byId.set(item.memoryId, { memoryId: item.memoryId, score: item.score, createdAt: op.at + i });
|
|
11744
|
+
});
|
|
11745
|
+
current = [...byId.values()].sort((a, b) => a.createdAt - b.createdAt).slice(-MAX_PER_CONVERSATION);
|
|
11746
|
+
}
|
|
11747
|
+
return plain({ links: current });
|
|
11748
|
+
}
|
|
11749
|
+
function toLinks(record2) {
|
|
11750
|
+
return links(record2.data).map((l) => ({
|
|
11751
|
+
uniqueId: `${record2.id}:${l.memoryId}`,
|
|
11752
|
+
conversationId: record2.id,
|
|
11753
|
+
memoryId: l.memoryId,
|
|
11754
|
+
score: l.score,
|
|
11755
|
+
createdAt: new Date(l.createdAt)
|
|
11756
|
+
}));
|
|
11757
|
+
}
|
|
11758
|
+
function bytes(value) {
|
|
11759
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
11760
|
+
}
|
|
11761
|
+
function fitRecord(record2) {
|
|
11762
|
+
if (record2.kind !== "message" || bytes(record2) <= recordBudgetBytes) return record2;
|
|
11763
|
+
const data = { ...record2.data };
|
|
11764
|
+
const truncated = [];
|
|
11765
|
+
for (const field10 of droppable) {
|
|
11766
|
+
if (bytes({ ...record2, data }) <= recordBudgetBytes) break;
|
|
11767
|
+
if (data[field10] === void 0) continue;
|
|
11768
|
+
delete data[field10];
|
|
11769
|
+
truncated.push(field10);
|
|
11770
|
+
}
|
|
11771
|
+
const content = text4(data.content) ?? "";
|
|
11772
|
+
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
11773
|
+
if (over > 0) {
|
|
11774
|
+
const encoded = new TextEncoder().encode(content);
|
|
11775
|
+
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
11776
|
+
truncated.push("content");
|
|
11777
|
+
}
|
|
11778
|
+
return { ...record2, data: { ...data, truncated } };
|
|
11779
|
+
}
|
|
11780
|
+
function acceptedVector(vector2) {
|
|
11781
|
+
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
11782
|
+
if (!vector2.every(Number.isFinite) || !vector2.slice(0, storedDims).some((x) => x !== 0))
|
|
11783
|
+
return void 0;
|
|
11784
|
+
return [...vector2];
|
|
11785
|
+
}
|
|
11786
|
+
function normalized(vector2) {
|
|
11787
|
+
const norm = Math.hypot(...vector2) || 1;
|
|
11788
|
+
return vector2.map((x) => x / norm);
|
|
11789
|
+
}
|
|
11790
|
+
function fitChunks(chunks3) {
|
|
11791
|
+
const usable = chunks3.map((c) => ({ ...c, vector: acceptedVector(c.vector) }));
|
|
11792
|
+
if (usable.length === 0 || usable.some((c) => !c.vector)) return void 0;
|
|
11793
|
+
if (usable.length <= maxChunks) return usable;
|
|
11794
|
+
const out = [];
|
|
11795
|
+
for (let g = 0; g < maxChunks; g++) {
|
|
11796
|
+
const group = usable.slice(
|
|
11797
|
+
Math.floor(g * usable.length / maxChunks),
|
|
11798
|
+
Math.floor((g + 1) * usable.length / maxChunks)
|
|
11799
|
+
);
|
|
11800
|
+
const dims = group[0].vector.length;
|
|
11801
|
+
const mean = new Array(dims).fill(0);
|
|
11802
|
+
for (const c of group) {
|
|
11803
|
+
const unit = normalized(c.vector);
|
|
11804
|
+
for (let d = 0; d < dims; d++) mean[d] += unit[d];
|
|
11805
|
+
}
|
|
11806
|
+
out.push({
|
|
11807
|
+
vector: normalized(mean),
|
|
11808
|
+
startOffset: group[0].startOffset,
|
|
11809
|
+
endOffset: group[group.length - 1].endOffset
|
|
11810
|
+
});
|
|
11811
|
+
}
|
|
11812
|
+
return out;
|
|
11813
|
+
}
|
|
11814
|
+
|
|
11815
|
+
// src/lib/chatStore/chatImports.ts
|
|
11816
|
+
var importBatch = 100;
|
|
11817
|
+
var importChunks = 200;
|
|
11818
|
+
var importPlaintextBytes = 39e5;
|
|
11819
|
+
function ms(date10, fallback = 1) {
|
|
11820
|
+
const value = date10?.getTime();
|
|
11821
|
+
return value && Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback;
|
|
11822
|
+
}
|
|
11823
|
+
function bytes2(value) {
|
|
11824
|
+
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
11825
|
+
}
|
|
11826
|
+
function conversationRecord(conversation, messages) {
|
|
11827
|
+
const createdAt = ms(conversation.createdAt);
|
|
11828
|
+
const data = plain({
|
|
11829
|
+
title: conversation.title,
|
|
11830
|
+
projectId: conversation.projectId || void 0,
|
|
11831
|
+
pinnedAt: conversation.pinnedAt ? ms(conversation.pinnedAt) : void 0,
|
|
11832
|
+
lastActivityAt: Math.max(
|
|
11833
|
+
ms(conversation.updatedAt, createdAt),
|
|
11834
|
+
...messages.map((m) => ms(m.createdAt))
|
|
11835
|
+
)
|
|
11836
|
+
});
|
|
11837
|
+
return {
|
|
11838
|
+
record: {
|
|
11839
|
+
kind: "conversation",
|
|
11840
|
+
id: conversation.conversationId,
|
|
11841
|
+
conversationId: "",
|
|
11842
|
+
sortKey: conversationSortKey(data, createdAt),
|
|
11843
|
+
createdAt,
|
|
11844
|
+
updatedAt: ms(conversation.updatedAt, createdAt),
|
|
11845
|
+
isDeleted: false,
|
|
11846
|
+
data
|
|
11847
|
+
}
|
|
11848
|
+
};
|
|
11849
|
+
}
|
|
11850
|
+
function messageRecord(message) {
|
|
11851
|
+
const {
|
|
11852
|
+
uniqueId: _uniqueId,
|
|
11853
|
+
messageId: _messageId,
|
|
11854
|
+
createdAt: _createdAt,
|
|
11855
|
+
updatedAt: _updatedAt,
|
|
11856
|
+
decryptionStatus: _status,
|
|
11857
|
+
chunks: chunks3,
|
|
11858
|
+
vector: vector2,
|
|
11859
|
+
...fields
|
|
11860
|
+
} = message;
|
|
11861
|
+
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
11862
|
+
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
11863
|
+
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
11864
|
+
const record2 = fitRecord({
|
|
11865
|
+
kind: "message",
|
|
11866
|
+
id: message.uniqueId,
|
|
11867
|
+
conversationId: message.conversationId,
|
|
11868
|
+
sortKey: message.messageId,
|
|
11869
|
+
createdAt: ms(message.createdAt),
|
|
11870
|
+
updatedAt: ms(message.updatedAt, ms(message.createdAt)),
|
|
11871
|
+
isDeleted: false,
|
|
11872
|
+
data: {
|
|
11873
|
+
...messageData(fields),
|
|
11874
|
+
...fitted ? { chunkOffsets: fitted.map((c) => [c.startOffset, c.endOffset]) } : {}
|
|
11875
|
+
}
|
|
11876
|
+
});
|
|
11877
|
+
return {
|
|
11878
|
+
record: record2,
|
|
11879
|
+
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
11880
|
+
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
11881
|
+
};
|
|
11882
|
+
}
|
|
11883
|
+
function batches(records) {
|
|
11884
|
+
const out = [];
|
|
11885
|
+
let batch = [];
|
|
11886
|
+
let chunks3 = 0;
|
|
11887
|
+
let size = 0;
|
|
11888
|
+
for (const item of records) {
|
|
11889
|
+
const vectors = item.embeddings?.length ?? 0;
|
|
11890
|
+
const itemSize = bytes2(item.record);
|
|
11891
|
+
if (batch.length > 0 && (batch.length >= importBatch || chunks3 + vectors > importChunks || size + itemSize > importPlaintextBytes)) {
|
|
11892
|
+
out.push(batch);
|
|
11893
|
+
batch = [];
|
|
11894
|
+
chunks3 = 0;
|
|
11895
|
+
size = 0;
|
|
11896
|
+
}
|
|
11897
|
+
batch.push(item);
|
|
11898
|
+
chunks3 += vectors;
|
|
11899
|
+
size += itemSize;
|
|
11900
|
+
}
|
|
11901
|
+
if (batch.length) out.push(batch);
|
|
11902
|
+
return out;
|
|
11903
|
+
}
|
|
11904
|
+
|
|
11636
11905
|
// src/lib/memory/store/remotePersistence.ts
|
|
11637
11906
|
init_portalLlm();
|
|
11638
11907
|
|
|
@@ -12375,7 +12644,7 @@ var ChatStoreError = class extends Error {
|
|
|
12375
12644
|
var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links"]);
|
|
12376
12645
|
var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
|
|
12377
12646
|
var maxPayload = 2 * 1024 * 1024;
|
|
12378
|
-
var
|
|
12647
|
+
var storedDims2 = 1536;
|
|
12379
12648
|
var maxRequestCiphertext = 8 * 1024 * 1024;
|
|
12380
12649
|
var maxGetRefs = 50;
|
|
12381
12650
|
var maxImportRecords = 100;
|
|
@@ -12443,24 +12712,24 @@ function vector(v) {
|
|
|
12443
12712
|
for (let i = 0; i < v.length; i++) {
|
|
12444
12713
|
const x = v[i];
|
|
12445
12714
|
if (typeof x !== "number" || !Number.isFinite(x)) return false;
|
|
12446
|
-
if (i <
|
|
12715
|
+
if (i < storedDims2 && x !== 0) nonZero = true;
|
|
12447
12716
|
}
|
|
12448
12717
|
return nonZero;
|
|
12449
12718
|
}
|
|
12450
12719
|
function vectorFields(write) {
|
|
12451
12720
|
return {
|
|
12452
|
-
...write.embeddings !== void 0 ? { embeddings: write.embeddings.map((v) => v.slice(0,
|
|
12721
|
+
...write.embeddings !== void 0 ? { embeddings: write.embeddings.map((v) => v.slice(0, storedDims2)) } : {},
|
|
12453
12722
|
...write.embeddingModel !== void 0 ? { embedding_model: write.embeddingModel } : {}
|
|
12454
12723
|
};
|
|
12455
12724
|
}
|
|
12456
|
-
function
|
|
12725
|
+
function text5(value) {
|
|
12457
12726
|
return typeof value === "string";
|
|
12458
12727
|
}
|
|
12459
12728
|
function timestamp(value) {
|
|
12460
12729
|
return typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
12461
12730
|
}
|
|
12462
12731
|
function presigned(value) {
|
|
12463
|
-
if (!object(value) || !
|
|
12732
|
+
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))
|
|
12464
12733
|
invalid();
|
|
12465
12734
|
return {
|
|
12466
12735
|
url: value.url,
|
|
@@ -12470,7 +12739,7 @@ function presigned(value) {
|
|
|
12470
12739
|
};
|
|
12471
12740
|
}
|
|
12472
12741
|
function attachment(value) {
|
|
12473
|
-
if (!object(value) || !
|
|
12742
|
+
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))
|
|
12474
12743
|
invalid();
|
|
12475
12744
|
return {
|
|
12476
12745
|
id: value.attachment_id,
|
|
@@ -12483,7 +12752,7 @@ function attachment(value) {
|
|
|
12483
12752
|
};
|
|
12484
12753
|
}
|
|
12485
12754
|
function ref(value) {
|
|
12486
|
-
if (!object(value) || !
|
|
12755
|
+
if (!object(value) || !text5(value.kind) || !kinds.has(value.kind) || !id(value.id)) invalid();
|
|
12487
12756
|
return { kind: value.kind, id: value.id };
|
|
12488
12757
|
}
|
|
12489
12758
|
function sameMetadata(a, b) {
|
|
@@ -12706,7 +12975,7 @@ async function createRemoteChatStore(options) {
|
|
|
12706
12975
|
},
|
|
12707
12976
|
async account(signal) {
|
|
12708
12977
|
const value = await request("/account", {}, signal);
|
|
12709
|
-
if (!object(value) || value.account_id !== accountId || !
|
|
12978
|
+
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))
|
|
12710
12979
|
invalid();
|
|
12711
12980
|
if (value.key_id && value.key_id !== keyId)
|
|
12712
12981
|
throw new ChatStoreError("Canonical chat key does not match", 409, "key_mismatch");
|
|
@@ -12781,12 +13050,12 @@ async function createRemoteChatStore(options) {
|
|
|
12781
13050
|
},
|
|
12782
13051
|
async changes(cursor, options2) {
|
|
12783
13052
|
const limit = options2?.limit ?? 100;
|
|
12784
|
-
if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!
|
|
13053
|
+
if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text5(cursor) || cursor.length > 2048))
|
|
12785
13054
|
invalid();
|
|
12786
13055
|
const params = new URLSearchParams({ account_id: String(accountId), limit: String(limit) });
|
|
12787
13056
|
if (cursor) params.set("cursor", cursor);
|
|
12788
13057
|
const value = await request(`/changes?${params}`, {}, options2?.signal);
|
|
12789
|
-
if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !
|
|
13058
|
+
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))
|
|
12790
13059
|
invalid();
|
|
12791
13060
|
const items = [];
|
|
12792
13061
|
for (const item of value.items) items.push(await decode(item));
|
|
@@ -12803,7 +13072,7 @@ async function createRemoteChatStore(options) {
|
|
|
12803
13072
|
if (!Array.isArray(embedding2) || !embeddings({
|
|
12804
13073
|
record: { ...emptyMessage, isDeleted: false },
|
|
12805
13074
|
embeddings: [embedding2]
|
|
12806
|
-
}) || !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 && (!
|
|
13075
|
+
}) || !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))
|
|
12807
13076
|
invalid();
|
|
12808
13077
|
const value = await request(
|
|
12809
13078
|
"/search",
|
|
@@ -12811,7 +13080,7 @@ async function createRemoteChatStore(options) {
|
|
|
12811
13080
|
method: "POST",
|
|
12812
13081
|
body: JSON.stringify({
|
|
12813
13082
|
account_id: accountId,
|
|
12814
|
-
embedding: embedding2.slice(0,
|
|
13083
|
+
embedding: embedding2.slice(0, storedDims2),
|
|
12815
13084
|
limit,
|
|
12816
13085
|
...kindsFilter ? { kinds: kindsFilter } : {},
|
|
12817
13086
|
...options2?.conversationId ? { conversation_id: options2.conversationId } : {},
|
|
@@ -12915,199 +13184,13 @@ var emptyMessage = {
|
|
|
12915
13184
|
data: {}
|
|
12916
13185
|
};
|
|
12917
13186
|
|
|
12918
|
-
// src/lib/chatStore/vaultRecords.ts
|
|
12919
|
-
var PINNED_SORT_BASE = 2 ** 51;
|
|
12920
|
-
var recordBudgetBytes = 104e4;
|
|
12921
|
-
var storedDims2 = 1536;
|
|
12922
|
-
var acceptedDims = /* @__PURE__ */ new Set([1536, 4096]);
|
|
12923
|
-
var maxChunks = 16;
|
|
12924
|
-
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
12925
|
-
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
12926
|
-
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
12927
|
-
function plain(value) {
|
|
12928
|
-
return JSON.parse(JSON.stringify(value ?? {}));
|
|
12929
|
-
}
|
|
12930
|
-
function text5(value) {
|
|
12931
|
-
return typeof value === "string" ? value : void 0;
|
|
12932
|
-
}
|
|
12933
|
-
function number(value) {
|
|
12934
|
-
return typeof value === "number" ? value : void 0;
|
|
12935
|
-
}
|
|
12936
|
-
function conversationSortKey(data, createdAt) {
|
|
12937
|
-
const pinnedAt = number(data.pinnedAt);
|
|
12938
|
-
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
12939
|
-
return number(data.lastActivityAt) ?? createdAt;
|
|
12940
|
-
}
|
|
12941
|
-
function toConversation(record2) {
|
|
12942
|
-
const pinnedAt = number(record2.data.pinnedAt);
|
|
12943
|
-
const projectId = text5(record2.data.projectId);
|
|
12944
|
-
return {
|
|
12945
|
-
uniqueId: record2.id,
|
|
12946
|
-
conversationId: record2.id,
|
|
12947
|
-
title: text5(record2.data.title) ?? "",
|
|
12948
|
-
...projectId ? { projectId } : {},
|
|
12949
|
-
createdAt: new Date(record2.createdAt),
|
|
12950
|
-
updatedAt: new Date(record2.updatedAt),
|
|
12951
|
-
isDeleted: record2.isDeleted,
|
|
12952
|
-
pinnedAt: pinnedAt ? new Date(pinnedAt) : null
|
|
12953
|
-
};
|
|
12954
|
-
}
|
|
12955
|
-
function messageData(options) {
|
|
12956
|
-
return plain(
|
|
12957
|
-
Object.fromEntries(
|
|
12958
|
-
Object.entries(options).filter(
|
|
12959
|
-
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
12960
|
-
)
|
|
12961
|
-
)
|
|
12962
|
-
);
|
|
12963
|
-
}
|
|
12964
|
-
function toMessage(record2) {
|
|
12965
|
-
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
12966
|
-
return {
|
|
12967
|
-
...fields,
|
|
12968
|
-
uniqueId: record2.id,
|
|
12969
|
-
messageId: record2.sortKey,
|
|
12970
|
-
conversationId: record2.conversationId,
|
|
12971
|
-
createdAt: new Date(record2.createdAt),
|
|
12972
|
-
updatedAt: new Date(record2.updatedAt)
|
|
12973
|
-
};
|
|
12974
|
-
}
|
|
12975
|
-
function chunkOffsets(record2) {
|
|
12976
|
-
const offsets = record2.data.chunkOffsets;
|
|
12977
|
-
return Array.isArray(offsets) ? offsets : void 0;
|
|
12978
|
-
}
|
|
12979
|
-
function toSkeletons(records) {
|
|
12980
|
-
const roleById = new Map(records.map((r) => [r.id, text5(r.data.role)]));
|
|
12981
|
-
return records.map((r) => {
|
|
12982
|
-
const parentMessageId = text5(r.data.parentMessageId);
|
|
12983
|
-
const model = text5(r.data.model);
|
|
12984
|
-
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
12985
|
-
return {
|
|
12986
|
-
uniqueId: r.id,
|
|
12987
|
-
messageId: r.sortKey,
|
|
12988
|
-
conversationId: r.conversationId,
|
|
12989
|
-
role: text5(r.data.role) ?? "",
|
|
12990
|
-
createdAt: new Date(r.createdAt),
|
|
12991
|
-
...parentMessageId ? { parentMessageId } : {},
|
|
12992
|
-
...model ? { model } : {},
|
|
12993
|
-
...artifact ? { content: text5(r.data.content) ?? "" } : {}
|
|
12994
|
-
};
|
|
12995
|
-
});
|
|
12996
|
-
}
|
|
12997
|
-
function toSummary(record2) {
|
|
12998
|
-
return {
|
|
12999
|
-
uniqueId: record2.id,
|
|
13000
|
-
conversationId: record2.id,
|
|
13001
|
-
summary: text5(record2.data.summary) ?? "",
|
|
13002
|
-
summarizedUpTo: text5(record2.data.summarizedUpTo) ?? "",
|
|
13003
|
-
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
13004
|
-
createdAt: new Date(record2.createdAt),
|
|
13005
|
-
updatedAt: new Date(record2.updatedAt)
|
|
13006
|
-
};
|
|
13007
|
-
}
|
|
13008
|
-
function links(data) {
|
|
13009
|
-
return Array.isArray(data.links) ? data.links : [];
|
|
13010
|
-
}
|
|
13011
|
-
function applyLinkOps(data, ops) {
|
|
13012
|
-
let current = links(data);
|
|
13013
|
-
for (const op of ops) {
|
|
13014
|
-
if ("clear" in op) {
|
|
13015
|
-
current = [];
|
|
13016
|
-
continue;
|
|
13017
|
-
}
|
|
13018
|
-
const byId = new Map(current.map((l) => [l.memoryId, l]));
|
|
13019
|
-
const turn = /* @__PURE__ */ new Set();
|
|
13020
|
-
op.add.forEach((item, i) => {
|
|
13021
|
-
if (!item.memoryId || turn.has(item.memoryId)) return;
|
|
13022
|
-
turn.add(item.memoryId);
|
|
13023
|
-
const known = byId.get(item.memoryId);
|
|
13024
|
-
if (known && known.createdAt >= op.at + i) return;
|
|
13025
|
-
byId.set(item.memoryId, { memoryId: item.memoryId, score: item.score, createdAt: op.at + i });
|
|
13026
|
-
});
|
|
13027
|
-
current = [...byId.values()].sort((a, b) => a.createdAt - b.createdAt).slice(-MAX_PER_CONVERSATION);
|
|
13028
|
-
}
|
|
13029
|
-
return plain({ links: current });
|
|
13030
|
-
}
|
|
13031
|
-
function toLinks(record2) {
|
|
13032
|
-
return links(record2.data).map((l) => ({
|
|
13033
|
-
uniqueId: `${record2.id}:${l.memoryId}`,
|
|
13034
|
-
conversationId: record2.id,
|
|
13035
|
-
memoryId: l.memoryId,
|
|
13036
|
-
score: l.score,
|
|
13037
|
-
createdAt: new Date(l.createdAt)
|
|
13038
|
-
}));
|
|
13039
|
-
}
|
|
13040
|
-
function bytes(value) {
|
|
13041
|
-
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
13042
|
-
}
|
|
13043
|
-
function fitRecord(record2) {
|
|
13044
|
-
if (record2.kind !== "message" || bytes(record2) <= recordBudgetBytes) return record2;
|
|
13045
|
-
const data = { ...record2.data };
|
|
13046
|
-
const truncated = [];
|
|
13047
|
-
for (const field10 of droppable) {
|
|
13048
|
-
if (bytes({ ...record2, data }) <= recordBudgetBytes) break;
|
|
13049
|
-
if (data[field10] === void 0) continue;
|
|
13050
|
-
delete data[field10];
|
|
13051
|
-
truncated.push(field10);
|
|
13052
|
-
}
|
|
13053
|
-
const content = text5(data.content) ?? "";
|
|
13054
|
-
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
13055
|
-
if (over > 0) {
|
|
13056
|
-
const encoded = new TextEncoder().encode(content);
|
|
13057
|
-
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
13058
|
-
truncated.push("content");
|
|
13059
|
-
}
|
|
13060
|
-
return { ...record2, data: { ...data, truncated } };
|
|
13061
|
-
}
|
|
13062
|
-
function acceptedVector(vector2) {
|
|
13063
|
-
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
13064
|
-
if (!vector2.every(Number.isFinite) || !vector2.slice(0, storedDims2).some((x) => x !== 0))
|
|
13065
|
-
return void 0;
|
|
13066
|
-
return [...vector2];
|
|
13067
|
-
}
|
|
13068
|
-
function normalized(vector2) {
|
|
13069
|
-
const norm = Math.hypot(...vector2) || 1;
|
|
13070
|
-
return vector2.map((x) => x / norm);
|
|
13071
|
-
}
|
|
13072
|
-
function fitChunks(chunks3) {
|
|
13073
|
-
const usable = chunks3.map((c) => ({ ...c, vector: acceptedVector(c.vector) }));
|
|
13074
|
-
if (usable.length === 0 || usable.some((c) => !c.vector)) return void 0;
|
|
13075
|
-
if (usable.length <= maxChunks) return usable;
|
|
13076
|
-
const out = [];
|
|
13077
|
-
for (let g = 0; g < maxChunks; g++) {
|
|
13078
|
-
const group = usable.slice(
|
|
13079
|
-
Math.floor(g * usable.length / maxChunks),
|
|
13080
|
-
Math.floor((g + 1) * usable.length / maxChunks)
|
|
13081
|
-
);
|
|
13082
|
-
const dims = group[0].vector.length;
|
|
13083
|
-
const mean = new Array(dims).fill(0);
|
|
13084
|
-
for (const c of group) {
|
|
13085
|
-
const unit = normalized(c.vector);
|
|
13086
|
-
for (let d = 0; d < dims; d++) mean[d] += unit[d];
|
|
13087
|
-
}
|
|
13088
|
-
out.push({
|
|
13089
|
-
vector: normalized(mean),
|
|
13090
|
-
startOffset: group[0].startOffset,
|
|
13091
|
-
endOffset: group[group.length - 1].endOffset
|
|
13092
|
-
});
|
|
13093
|
-
}
|
|
13094
|
-
return out;
|
|
13095
|
-
}
|
|
13096
|
-
|
|
13097
13187
|
// src/lib/chatStore/migrateChats.ts
|
|
13098
13188
|
var maxPasses = 5;
|
|
13099
13189
|
var verifyBatch = 1e3;
|
|
13100
|
-
var importBatch = 100;
|
|
13101
|
-
var importChunks = 200;
|
|
13102
|
-
var importPlaintextBytes = 39e5;
|
|
13103
13190
|
var writeBatch = 25;
|
|
13104
13191
|
function key(record2) {
|
|
13105
13192
|
return `${record2.kind}/${record2.id}`;
|
|
13106
13193
|
}
|
|
13107
|
-
function ms(date10, fallback = 1) {
|
|
13108
|
-
const value = date10?.getTime();
|
|
13109
|
-
return value && Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback;
|
|
13110
|
-
}
|
|
13111
13194
|
function sealed(value) {
|
|
13112
13195
|
if (typeof value === "string") return isEncrypted(value);
|
|
13113
13196
|
if (Array.isArray(value)) return typeof value[0] !== "number" && value.some(sealed);
|
|
@@ -13115,42 +13198,6 @@ function sealed(value) {
|
|
|
13115
13198
|
return Object.values(value).some(sealed);
|
|
13116
13199
|
return false;
|
|
13117
13200
|
}
|
|
13118
|
-
function bytes2(value) {
|
|
13119
|
-
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
13120
|
-
}
|
|
13121
|
-
function messageRecord(message) {
|
|
13122
|
-
const {
|
|
13123
|
-
uniqueId: _uniqueId,
|
|
13124
|
-
messageId: _messageId,
|
|
13125
|
-
createdAt: _createdAt,
|
|
13126
|
-
updatedAt: _updatedAt,
|
|
13127
|
-
decryptionStatus: _status,
|
|
13128
|
-
chunks: chunks3,
|
|
13129
|
-
vector: vector2,
|
|
13130
|
-
...fields
|
|
13131
|
-
} = message;
|
|
13132
|
-
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
13133
|
-
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
13134
|
-
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
13135
|
-
const record2 = fitRecord({
|
|
13136
|
-
kind: "message",
|
|
13137
|
-
id: message.uniqueId,
|
|
13138
|
-
conversationId: message.conversationId,
|
|
13139
|
-
sortKey: message.messageId,
|
|
13140
|
-
createdAt: ms(message.createdAt),
|
|
13141
|
-
updatedAt: ms(message.updatedAt, ms(message.createdAt)),
|
|
13142
|
-
isDeleted: false,
|
|
13143
|
-
data: {
|
|
13144
|
-
...messageData(fields),
|
|
13145
|
-
...fitted ? { chunkOffsets: fitted.map((c) => [c.startOffset, c.endOffset]) } : {}
|
|
13146
|
-
}
|
|
13147
|
-
});
|
|
13148
|
-
return {
|
|
13149
|
-
record: record2,
|
|
13150
|
-
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
13151
|
-
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
13152
|
-
};
|
|
13153
|
-
}
|
|
13154
13201
|
async function readLocal(options) {
|
|
13155
13202
|
const { database } = options;
|
|
13156
13203
|
const ctx = {
|
|
@@ -13204,29 +13251,10 @@ async function readLocal(options) {
|
|
|
13204
13251
|
const messages = await getMessagesOp(ctx, conversationId);
|
|
13205
13252
|
const unreadableTitle = isEncrypted(conversation.title);
|
|
13206
13253
|
if (unreadableTitle) out.untitled++;
|
|
13207
|
-
const createdAt = ms(conversation.createdAt);
|
|
13208
|
-
const data = plain({
|
|
13209
|
-
title: unreadableTitle ? "" : conversation.title,
|
|
13210
|
-
projectId: conversation.projectId || void 0,
|
|
13211
|
-
pinnedAt: conversation.pinnedAt ? ms(conversation.pinnedAt) : void 0,
|
|
13212
|
-
lastActivityAt: Math.max(
|
|
13213
|
-
ms(conversation.updatedAt, createdAt),
|
|
13214
|
-
...messages.map((m) => ms(m.createdAt))
|
|
13215
|
-
)
|
|
13216
|
-
});
|
|
13217
13254
|
out.conversations++;
|
|
13218
|
-
out.records.push(
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
id: conversationId,
|
|
13222
|
-
conversationId: "",
|
|
13223
|
-
sortKey: conversationSortKey(data, createdAt),
|
|
13224
|
-
createdAt,
|
|
13225
|
-
updatedAt: ms(conversation.updatedAt, createdAt),
|
|
13226
|
-
isDeleted: false,
|
|
13227
|
-
data
|
|
13228
|
-
}
|
|
13229
|
-
});
|
|
13255
|
+
out.records.push(
|
|
13256
|
+
conversationRecord(unreadableTitle ? { ...conversation, title: "" } : conversation, messages)
|
|
13257
|
+
);
|
|
13230
13258
|
for (const message of messages) {
|
|
13231
13259
|
if (message.decryptionStatus || sealed(message)) {
|
|
13232
13260
|
skip("message", message.uniqueId, "unreadable");
|
|
@@ -13347,27 +13375,6 @@ async function deletedSinceUpload(store, journal, local, signal) {
|
|
|
13347
13375
|
};
|
|
13348
13376
|
});
|
|
13349
13377
|
}
|
|
13350
|
-
function batches(records) {
|
|
13351
|
-
const out = [];
|
|
13352
|
-
let batch = [];
|
|
13353
|
-
let chunks3 = 0;
|
|
13354
|
-
let size = 0;
|
|
13355
|
-
for (const item of records) {
|
|
13356
|
-
const vectors = item.embeddings?.length ?? 0;
|
|
13357
|
-
const itemSize = bytes2(item.record);
|
|
13358
|
-
if (batch.length > 0 && (batch.length >= importBatch || chunks3 + vectors > importChunks || size + itemSize > importPlaintextBytes)) {
|
|
13359
|
-
out.push(batch);
|
|
13360
|
-
batch = [];
|
|
13361
|
-
chunks3 = 0;
|
|
13362
|
-
size = 0;
|
|
13363
|
-
}
|
|
13364
|
-
batch.push(item);
|
|
13365
|
-
chunks3 += vectors;
|
|
13366
|
-
size += itemSize;
|
|
13367
|
-
}
|
|
13368
|
-
if (batch.length) out.push(batch);
|
|
13369
|
-
return out;
|
|
13370
|
-
}
|
|
13371
13378
|
function fitVectors(records, available2, unembedded) {
|
|
13372
13379
|
let total = records.reduce((sum, r) => sum + (r.embeddings?.length ?? 0), 0);
|
|
13373
13380
|
if (total <= available2) return records;
|
|
@@ -14448,6 +14455,45 @@ function createVaultChatBackend(options) {
|
|
|
14448
14455
|
},
|
|
14449
14456
|
flush,
|
|
14450
14457
|
poll,
|
|
14458
|
+
async importChats(chats) {
|
|
14459
|
+
await ready();
|
|
14460
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14461
|
+
const unique = (items) => items.filter(({ record: record2 }) => {
|
|
14462
|
+
const k = key2(record2.kind, record2.id);
|
|
14463
|
+
if (seen.has(k)) return false;
|
|
14464
|
+
seen.add(k);
|
|
14465
|
+
return true;
|
|
14466
|
+
});
|
|
14467
|
+
const valid = chats.filter((c) => validChatId(c.conversation.conversationId));
|
|
14468
|
+
const conversations = unique(
|
|
14469
|
+
valid.map((c) => conversationRecord(c.conversation, c.messages))
|
|
14470
|
+
);
|
|
14471
|
+
const messages = unique(
|
|
14472
|
+
valid.flatMap(
|
|
14473
|
+
(c) => c.messages.filter(
|
|
14474
|
+
(m) => m.conversationId === c.conversation.conversationId && validChatId(m.uniqueId) && Number.isSafeInteger(m.messageId)
|
|
14475
|
+
).map((m) => messageRecord({ ...m, vector: void 0, chunks: void 0 }))
|
|
14476
|
+
)
|
|
14477
|
+
);
|
|
14478
|
+
let conversationCount = 0;
|
|
14479
|
+
let messageCount = 0;
|
|
14480
|
+
try {
|
|
14481
|
+
for (const batch of batches(conversations))
|
|
14482
|
+
conversationCount += await store.importRecords(batch);
|
|
14483
|
+
for (const batch of batches(messages)) messageCount += await store.importRecords(batch);
|
|
14484
|
+
} finally {
|
|
14485
|
+
for (const { record: record2 } of messages) checked.delete(key2("message", record2.id));
|
|
14486
|
+
await refresh(conversations.map(({ record: record2 }) => key2("conversation", record2.id))).catch(
|
|
14487
|
+
() => void 0
|
|
14488
|
+
);
|
|
14489
|
+
for (const { record: record2 } of conversations) threads.delete(record2.id);
|
|
14490
|
+
channel?.postMessage("changed");
|
|
14491
|
+
emit({ type: "conversations", origin: "local" });
|
|
14492
|
+
for (const { record: record2 } of conversations)
|
|
14493
|
+
emit({ type: "messages", conversationId: record2.id, origin: "local" });
|
|
14494
|
+
}
|
|
14495
|
+
return { conversations: conversationCount, messages: messageCount };
|
|
14496
|
+
},
|
|
14451
14497
|
status: () => ({ pending: pending.size + inflight.size, ...stopped ? { stopped } : {} }),
|
|
14452
14498
|
close() {
|
|
14453
14499
|
closed = true;
|