@anuma/sdk 10.3.0 → 10.4.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 +418 -22
- package/dist/expo/index.d.mts +610 -527
- package/dist/expo/index.d.ts +610 -527
- package/dist/expo/index.mjs +414 -22
- package/dist/index.d.mts +154 -154
- package/dist/index.d.ts +154 -154
- package/dist/react/index.cjs +418 -22
- package/dist/react/index.d.mts +1055 -972
- package/dist/react/index.d.ts +1055 -972
- package/dist/react/index.mjs +414 -22
- package/dist/server/index.d.mts +10 -0
- package/dist/server/index.d.ts +10 -0
- package/package.json +1 -1
package/dist/expo/index.mjs
CHANGED
|
@@ -11855,6 +11855,360 @@ async function migrateChatsToRemote(options) {
|
|
|
11855
11855
|
return passes(false);
|
|
11856
11856
|
}
|
|
11857
11857
|
|
|
11858
|
+
// src/lib/chatStore/vaultAttachments.ts
|
|
11859
|
+
var frameVersion = 1;
|
|
11860
|
+
var ivBytes = 12;
|
|
11861
|
+
var tagBytes = 16;
|
|
11862
|
+
var frameOverhead = 1 + ivBytes + tagBytes;
|
|
11863
|
+
var maxCiphertextBytes = 50 * 1024 * 1024;
|
|
11864
|
+
var expirySkewMs = 3e4;
|
|
11865
|
+
var maxRetryAfterMs = 3e4;
|
|
11866
|
+
var maxRefWrites = 5;
|
|
11867
|
+
var uploadWindowMs = 16 * 6e4;
|
|
11868
|
+
var attachmentIdPattern2 = /^[0-9a-f]{32}$/;
|
|
11869
|
+
var maxVaultAttachmentBytes = maxCiphertextBytes - frameOverhead;
|
|
11870
|
+
function additionalData(attachmentId) {
|
|
11871
|
+
return new TextEncoder().encode(`anuma-chat-attachment-v1:${attachmentId}`);
|
|
11872
|
+
}
|
|
11873
|
+
function invalidAttachment() {
|
|
11874
|
+
throw new ChatStoreError("Attachment does not decrypt under this key", 0, "invalid_attachment");
|
|
11875
|
+
}
|
|
11876
|
+
function sendableHeaders(headers) {
|
|
11877
|
+
return Object.fromEntries(
|
|
11878
|
+
Object.entries(headers).filter(([name]) => name.toLowerCase() !== "content-length")
|
|
11879
|
+
);
|
|
11880
|
+
}
|
|
11881
|
+
function transientStatus(status) {
|
|
11882
|
+
return status === 429 || status >= 500;
|
|
11883
|
+
}
|
|
11884
|
+
async function discardBody(response) {
|
|
11885
|
+
await response.body?.cancel().catch(() => void 0);
|
|
11886
|
+
}
|
|
11887
|
+
function createVaultAttachments(options) {
|
|
11888
|
+
const { store, keyRing, cache } = options;
|
|
11889
|
+
const fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
11890
|
+
const retries = options.retries ?? 3;
|
|
11891
|
+
const retryDelayMs = options.retryDelayMs ?? 500;
|
|
11892
|
+
const now = options.now ?? Date.now;
|
|
11893
|
+
const sleep3 = (ms2, signal) => new Promise((resolve, reject) => {
|
|
11894
|
+
signal?.throwIfAborted();
|
|
11895
|
+
const timer = setTimeout(() => {
|
|
11896
|
+
signal?.removeEventListener("abort", onAbort);
|
|
11897
|
+
resolve();
|
|
11898
|
+
}, ms2);
|
|
11899
|
+
const onAbort = () => {
|
|
11900
|
+
clearTimeout(timer);
|
|
11901
|
+
reject(signal?.reason);
|
|
11902
|
+
};
|
|
11903
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
11904
|
+
});
|
|
11905
|
+
const pause = (attempt, signal, atLeast = 0) => sleep3(Math.max(atLeast, retryDelayMs * 2 ** attempt), signal);
|
|
11906
|
+
const withRetry = async (call, signal) => {
|
|
11907
|
+
for (let attempt = 0; ; attempt++) {
|
|
11908
|
+
try {
|
|
11909
|
+
return await call();
|
|
11910
|
+
} catch (error) {
|
|
11911
|
+
if (!(error instanceof ChatStoreError) || !transientStatus(error.status) || attempt >= retries || (error.retryAfterMs ?? 0) > maxRetryAfterMs)
|
|
11912
|
+
throw error;
|
|
11913
|
+
await pause(attempt, signal, error.retryAfterMs);
|
|
11914
|
+
}
|
|
11915
|
+
}
|
|
11916
|
+
};
|
|
11917
|
+
const expired = (url) => now() >= Date.parse(url.expiresAt) - expirySkewMs;
|
|
11918
|
+
const seal = async (bytes4, attachmentId) => {
|
|
11919
|
+
const iv = crypto.getRandomValues(new Uint8Array(ivBytes));
|
|
11920
|
+
const sealed2 = new Uint8Array(
|
|
11921
|
+
await crypto.subtle.encrypt(
|
|
11922
|
+
{ name: "AES-GCM", iv, additionalData: additionalData(attachmentId) },
|
|
11923
|
+
keyRing.v3,
|
|
11924
|
+
bytes4
|
|
11925
|
+
)
|
|
11926
|
+
);
|
|
11927
|
+
const frame = new Uint8Array(1 + ivBytes + sealed2.length);
|
|
11928
|
+
frame[0] = frameVersion;
|
|
11929
|
+
frame.set(iv, 1);
|
|
11930
|
+
frame.set(sealed2, 1 + ivBytes);
|
|
11931
|
+
return frame;
|
|
11932
|
+
};
|
|
11933
|
+
const open = async (frame, attachmentId) => {
|
|
11934
|
+
if (frame.length < frameOverhead || frame[0] !== frameVersion) invalidAttachment();
|
|
11935
|
+
try {
|
|
11936
|
+
return new Uint8Array(
|
|
11937
|
+
await crypto.subtle.decrypt(
|
|
11938
|
+
{
|
|
11939
|
+
name: "AES-GCM",
|
|
11940
|
+
iv: frame.slice(1, 1 + ivBytes),
|
|
11941
|
+
additionalData: additionalData(attachmentId)
|
|
11942
|
+
},
|
|
11943
|
+
keyRing.v3,
|
|
11944
|
+
frame.slice(1 + ivBytes)
|
|
11945
|
+
)
|
|
11946
|
+
);
|
|
11947
|
+
} catch {
|
|
11948
|
+
return invalidAttachment();
|
|
11949
|
+
}
|
|
11950
|
+
};
|
|
11951
|
+
const put = async (upload, body, signal) => {
|
|
11952
|
+
for (let attempt = 0; ; attempt++) {
|
|
11953
|
+
if (expired(upload)) return "expired";
|
|
11954
|
+
let response;
|
|
11955
|
+
try {
|
|
11956
|
+
response = await fetcher(upload.url, {
|
|
11957
|
+
method: upload.method,
|
|
11958
|
+
headers: sendableHeaders(upload.headers),
|
|
11959
|
+
body,
|
|
11960
|
+
signal
|
|
11961
|
+
});
|
|
11962
|
+
} catch (error) {
|
|
11963
|
+
if (signal?.aborted || attempt >= retries) throw error;
|
|
11964
|
+
await pause(attempt, signal);
|
|
11965
|
+
continue;
|
|
11966
|
+
}
|
|
11967
|
+
await discardBody(response);
|
|
11968
|
+
if (response.ok) return "stored";
|
|
11969
|
+
if (response.status === 403) return "expired";
|
|
11970
|
+
if (!transientStatus(response.status) || attempt >= retries)
|
|
11971
|
+
throw new ChatStoreError(
|
|
11972
|
+
`Attachment upload failed with ${response.status}`,
|
|
11973
|
+
response.status,
|
|
11974
|
+
"attachment_upload_failed"
|
|
11975
|
+
);
|
|
11976
|
+
await pause(attempt, signal);
|
|
11977
|
+
}
|
|
11978
|
+
};
|
|
11979
|
+
const download = async (url, signal) => {
|
|
11980
|
+
for (let attempt = 0; ; attempt++) {
|
|
11981
|
+
if (expired(url)) return "expired";
|
|
11982
|
+
let response;
|
|
11983
|
+
try {
|
|
11984
|
+
response = await fetcher(url.url, {
|
|
11985
|
+
method: url.method,
|
|
11986
|
+
headers: sendableHeaders(url.headers),
|
|
11987
|
+
signal
|
|
11988
|
+
});
|
|
11989
|
+
if (response.ok) return new Uint8Array(await response.arrayBuffer());
|
|
11990
|
+
} catch (error) {
|
|
11991
|
+
if (signal?.aborted || attempt >= retries) throw error;
|
|
11992
|
+
await pause(attempt, signal);
|
|
11993
|
+
continue;
|
|
11994
|
+
}
|
|
11995
|
+
await discardBody(response);
|
|
11996
|
+
if (response.status === 403) return "expired";
|
|
11997
|
+
if (response.status === 404) return "missing";
|
|
11998
|
+
if (!transientStatus(response.status) || attempt >= retries)
|
|
11999
|
+
throw new ChatStoreError(
|
|
12000
|
+
`Attachment download failed with ${response.status}`,
|
|
12001
|
+
response.status,
|
|
12002
|
+
"attachment_download_failed"
|
|
12003
|
+
);
|
|
12004
|
+
await pause(attempt, signal);
|
|
12005
|
+
}
|
|
12006
|
+
};
|
|
12007
|
+
const remove = async (attachmentId, signal) => {
|
|
12008
|
+
try {
|
|
12009
|
+
await withRetry(() => store.attachments.delete(attachmentId, signal), signal);
|
|
12010
|
+
} catch (error) {
|
|
12011
|
+
if (!(error instanceof ChatStoreError) || error.status !== 404) throw error;
|
|
12012
|
+
}
|
|
12013
|
+
await cache?.delete(attachmentId).catch(() => void 0);
|
|
12014
|
+
};
|
|
12015
|
+
const discardPending = async (attachmentId) => {
|
|
12016
|
+
const found = await store.attachments.get(attachmentId);
|
|
12017
|
+
if (found?.attachment.state === "pending") await remove(attachmentId);
|
|
12018
|
+
};
|
|
12019
|
+
return {
|
|
12020
|
+
async upload(bytes4, uploadOptions) {
|
|
12021
|
+
const signal = uploadOptions?.signal;
|
|
12022
|
+
if (!(bytes4 instanceof Uint8Array) || bytes4.length > maxVaultAttachmentBytes)
|
|
12023
|
+
throw new ChatStoreError(
|
|
12024
|
+
"Attachment is larger than vault accepts",
|
|
12025
|
+
413,
|
|
12026
|
+
"attachment_too_large"
|
|
12027
|
+
);
|
|
12028
|
+
const size = bytes4.length + frameOverhead;
|
|
12029
|
+
for (let attempt = 0; ; attempt++) {
|
|
12030
|
+
const { attachment: attachment2, upload } = await withRetry(
|
|
12031
|
+
() => store.attachments.create(size, signal),
|
|
12032
|
+
signal
|
|
12033
|
+
);
|
|
12034
|
+
try {
|
|
12035
|
+
await uploadOptions?.onReserved?.(attachment2.id);
|
|
12036
|
+
const frame = await seal(bytes4, attachment2.id);
|
|
12037
|
+
if (await put(upload, frame, signal) === "stored") return attachment2.id;
|
|
12038
|
+
} catch (error) {
|
|
12039
|
+
await discardPending(attachment2.id).catch(() => void 0);
|
|
12040
|
+
throw error;
|
|
12041
|
+
}
|
|
12042
|
+
await remove(attachment2.id).catch(() => void 0);
|
|
12043
|
+
if (attempt >= retries)
|
|
12044
|
+
throw new ChatStoreError(
|
|
12045
|
+
"Attachment storage rejected the upload URL",
|
|
12046
|
+
403,
|
|
12047
|
+
"attachment_upload_rejected"
|
|
12048
|
+
);
|
|
12049
|
+
}
|
|
12050
|
+
},
|
|
12051
|
+
commit(attachmentId, owner, signal) {
|
|
12052
|
+
return withRetry(() => store.attachments.commit(attachmentId, owner, signal), signal);
|
|
12053
|
+
},
|
|
12054
|
+
async read(attachmentId, signal) {
|
|
12055
|
+
if (!attachmentIdPattern2.test(attachmentId)) invalidAttachment();
|
|
12056
|
+
const cached = await cache?.get(attachmentId).catch(() => null);
|
|
12057
|
+
if (cached) return cached;
|
|
12058
|
+
for (let attempt = 0; ; attempt++) {
|
|
12059
|
+
const found = await withRetry(() => store.attachments.get(attachmentId, signal), signal);
|
|
12060
|
+
if (!found?.download) return null;
|
|
12061
|
+
const frame = await download(found.download, signal);
|
|
12062
|
+
if (frame === "missing") return null;
|
|
12063
|
+
if (frame === "expired") {
|
|
12064
|
+
if (attempt >= retries)
|
|
12065
|
+
throw new ChatStoreError(
|
|
12066
|
+
"Attachment storage rejected the download URL",
|
|
12067
|
+
403,
|
|
12068
|
+
"attachment_download_rejected"
|
|
12069
|
+
);
|
|
12070
|
+
continue;
|
|
12071
|
+
}
|
|
12072
|
+
if (frame.length !== found.attachment.sizeBytes) invalidAttachment();
|
|
12073
|
+
const bytes4 = await open(frame, attachmentId);
|
|
12074
|
+
await cache?.set(attachmentId, bytes4).catch(() => void 0);
|
|
12075
|
+
return bytes4;
|
|
12076
|
+
}
|
|
12077
|
+
},
|
|
12078
|
+
delete: remove
|
|
12079
|
+
};
|
|
12080
|
+
}
|
|
12081
|
+
function validRef(value) {
|
|
12082
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
12083
|
+
const ref3 = value;
|
|
12084
|
+
return typeof ref3.attachmentId === "string" && attachmentIdPattern2.test(ref3.attachmentId) && typeof ref3.fileId === "string" && ref3.fileId.length > 0 && typeof ref3.name === "string" && typeof ref3.type === "string" && Number.isSafeInteger(ref3.size) && ref3.size >= 0;
|
|
12085
|
+
}
|
|
12086
|
+
function vaultAttachmentRefs(record2) {
|
|
12087
|
+
const refs = record2.data.vaultAttachments;
|
|
12088
|
+
return Array.isArray(refs) ? refs.filter(validRef) : [];
|
|
12089
|
+
}
|
|
12090
|
+
function journalKey(messageId, fileId) {
|
|
12091
|
+
return JSON.stringify([messageId, fileId]);
|
|
12092
|
+
}
|
|
12093
|
+
async function migrateMessageAttachments(options) {
|
|
12094
|
+
const { store, attachments, journal, messageId, signal } = options;
|
|
12095
|
+
const now = options.now ?? Date.now;
|
|
12096
|
+
const owner = { kind: "message", id: messageId };
|
|
12097
|
+
const ownerGone = () => new ChatStoreError("Message is not in vault", 409, "attachment_owner_not_found");
|
|
12098
|
+
let snapshot = await store.get("message", messageId, signal);
|
|
12099
|
+
if (!snapshot || snapshot.record.isDeleted) throw ownerGone();
|
|
12100
|
+
const present = new Map(vaultAttachmentRefs(snapshot.record).map((r) => [r.fileId, r]));
|
|
12101
|
+
const uploadable = (attachment2) => attachment2.state === "pending" && now() < Date.parse(attachment2.createdAt) + uploadWindowMs;
|
|
12102
|
+
const lookup = async (attachmentId) => attachmentId && attachmentIdPattern2.test(attachmentId) ? (await store.attachments.get(attachmentId, signal))?.attachment ?? null : null;
|
|
12103
|
+
const bind = async (found) => {
|
|
12104
|
+
if (!found) return null;
|
|
12105
|
+
if (found.state === "committed")
|
|
12106
|
+
return found.ownerKind === owner.kind && found.ownerId === owner.id ? found : null;
|
|
12107
|
+
try {
|
|
12108
|
+
return await attachments.commit(found.id, owner, signal);
|
|
12109
|
+
} catch (error) {
|
|
12110
|
+
if (!(error instanceof ChatStoreError) || error.code !== "attachment_not_uploaded")
|
|
12111
|
+
throw error;
|
|
12112
|
+
if (uploadable(found)) return "busy";
|
|
12113
|
+
await attachments.delete(found.id, signal);
|
|
12114
|
+
return null;
|
|
12115
|
+
}
|
|
12116
|
+
};
|
|
12117
|
+
const added = [];
|
|
12118
|
+
const settled = [];
|
|
12119
|
+
const missing2 = [];
|
|
12120
|
+
const oversized = [];
|
|
12121
|
+
const deferred = [];
|
|
12122
|
+
const stale = /* @__PURE__ */ new Set();
|
|
12123
|
+
let uploaded = 0;
|
|
12124
|
+
for (const file of options.files) {
|
|
12125
|
+
signal?.throwIfAborted();
|
|
12126
|
+
const key3 = journalKey(messageId, file.fileId);
|
|
12127
|
+
const recorded = present.get(file.fileId);
|
|
12128
|
+
if (recorded) {
|
|
12129
|
+
const bound = await bind(await lookup(recorded.attachmentId));
|
|
12130
|
+
if (bound === "busy") {
|
|
12131
|
+
deferred.push(file.fileId);
|
|
12132
|
+
continue;
|
|
12133
|
+
}
|
|
12134
|
+
if (bound) {
|
|
12135
|
+
const stray = await lookup(await journal.get(key3));
|
|
12136
|
+
if (stray && stray.id !== recorded.attachmentId) {
|
|
12137
|
+
if (uploadable(stray)) continue;
|
|
12138
|
+
await attachments.delete(stray.id, signal);
|
|
12139
|
+
}
|
|
12140
|
+
settled.push(key3);
|
|
12141
|
+
continue;
|
|
12142
|
+
}
|
|
12143
|
+
stale.add(recorded.attachmentId);
|
|
12144
|
+
}
|
|
12145
|
+
const meta = { fileId: file.fileId, name: file.name, type: file.type };
|
|
12146
|
+
const resumed = await bind(await lookup(await journal.get(key3)));
|
|
12147
|
+
if (resumed === "busy") {
|
|
12148
|
+
deferred.push(file.fileId);
|
|
12149
|
+
continue;
|
|
12150
|
+
}
|
|
12151
|
+
if (resumed) {
|
|
12152
|
+
added.push({ attachmentId: resumed.id, ...meta, size: resumed.sizeBytes - frameOverhead });
|
|
12153
|
+
settled.push(key3);
|
|
12154
|
+
continue;
|
|
12155
|
+
}
|
|
12156
|
+
const bytes4 = await file.read();
|
|
12157
|
+
if (!bytes4) {
|
|
12158
|
+
missing2.push(file.fileId);
|
|
12159
|
+
continue;
|
|
12160
|
+
}
|
|
12161
|
+
if (bytes4.length > maxVaultAttachmentBytes) {
|
|
12162
|
+
oversized.push(file.fileId);
|
|
12163
|
+
continue;
|
|
12164
|
+
}
|
|
12165
|
+
const attachmentId = await attachments.upload(bytes4, {
|
|
12166
|
+
signal,
|
|
12167
|
+
onReserved: (id2) => journal.set(key3, id2)
|
|
12168
|
+
});
|
|
12169
|
+
uploaded++;
|
|
12170
|
+
await attachments.commit(attachmentId, owner, signal);
|
|
12171
|
+
added.push({ attachmentId, ...meta, size: bytes4.length });
|
|
12172
|
+
settled.push(key3);
|
|
12173
|
+
}
|
|
12174
|
+
const superseded = [];
|
|
12175
|
+
for (let attempt = 0; added.length > 0; attempt++) {
|
|
12176
|
+
const refs = new Map(vaultAttachmentRefs(snapshot.record).map((r) => [r.fileId, r]));
|
|
12177
|
+
superseded.length = 0;
|
|
12178
|
+
for (const ref3 of added) {
|
|
12179
|
+
const prior = refs.get(ref3.fileId);
|
|
12180
|
+
if (prior && prior.attachmentId !== ref3.attachmentId && !stale.has(prior.attachmentId))
|
|
12181
|
+
superseded.push(ref3.attachmentId);
|
|
12182
|
+
else refs.set(ref3.fileId, ref3);
|
|
12183
|
+
}
|
|
12184
|
+
if (superseded.length === added.length) break;
|
|
12185
|
+
try {
|
|
12186
|
+
[snapshot] = await store.putMany(
|
|
12187
|
+
[
|
|
12188
|
+
{
|
|
12189
|
+
record: {
|
|
12190
|
+
...snapshot.record,
|
|
12191
|
+
data: { ...snapshot.record.data, ...plain({ vaultAttachments: [...refs.values()] }) }
|
|
12192
|
+
},
|
|
12193
|
+
expectedVersion: snapshot.version
|
|
12194
|
+
}
|
|
12195
|
+
],
|
|
12196
|
+
signal
|
|
12197
|
+
);
|
|
12198
|
+
break;
|
|
12199
|
+
} catch (error) {
|
|
12200
|
+
if (!(error instanceof ChatStoreError) || error.code !== "version_conflict" || attempt + 1 >= maxRefWrites)
|
|
12201
|
+
throw error;
|
|
12202
|
+
const latest = await store.get("message", messageId, signal);
|
|
12203
|
+
if (!latest || latest.record.isDeleted) throw ownerGone();
|
|
12204
|
+
snapshot = latest;
|
|
12205
|
+
}
|
|
12206
|
+
}
|
|
12207
|
+
for (const id2 of superseded) await attachments.delete(id2, signal);
|
|
12208
|
+
for (const key3 of settled) await journal.set(key3, null);
|
|
12209
|
+
return { refs: vaultAttachmentRefs(snapshot.record), uploaded, missing: missing2, oversized, deferred };
|
|
12210
|
+
}
|
|
12211
|
+
|
|
11858
12212
|
// src/lib/chatStore/vaultBackend.ts
|
|
11859
12213
|
import { v7 as uuidv73 } from "uuid";
|
|
11860
12214
|
|
|
@@ -11994,6 +12348,7 @@ var resumableFields = [
|
|
|
11994
12348
|
"imageModel",
|
|
11995
12349
|
"files",
|
|
11996
12350
|
"fileIds",
|
|
12351
|
+
"vaultAttachments",
|
|
11997
12352
|
"usage",
|
|
11998
12353
|
"sources",
|
|
11999
12354
|
"responseDuration",
|
|
@@ -24231,7 +24586,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24231
24586
|
};
|
|
24232
24587
|
const mutate = (id2, change, edit, writeOptions) => serialized(id2, () => mutateLocked(id2, change, edit, writeOptions));
|
|
24233
24588
|
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id2) => () => serialized(id2, inner), task)();
|
|
24234
|
-
const mutateMany = async (ids, change, edit, leaseToken, signal) => {
|
|
24589
|
+
const mutateMany = async (ids, change, edit, leaseToken, signal, includeEmbeddings = false) => {
|
|
24235
24590
|
const saved = /* @__PURE__ */ new Map();
|
|
24236
24591
|
const failed = /* @__PURE__ */ new Map();
|
|
24237
24592
|
for (const slice of chunks2([...new Set(ids)], MAX_BATCH)) {
|
|
@@ -24240,7 +24595,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24240
24595
|
const writes = [];
|
|
24241
24596
|
let read;
|
|
24242
24597
|
try {
|
|
24243
|
-
read = await readEveryState(slice, signal);
|
|
24598
|
+
read = await readEveryState(slice, signal, includeEmbeddings);
|
|
24244
24599
|
} catch (error) {
|
|
24245
24600
|
signal?.throwIfAborted();
|
|
24246
24601
|
for (const id2 of slice) failed.set(id2, error);
|
|
@@ -24299,21 +24654,55 @@ function createRemoteMemoryStore(options) {
|
|
|
24299
24654
|
}
|
|
24300
24655
|
return { saved, failed };
|
|
24301
24656
|
};
|
|
24302
|
-
const
|
|
24303
|
-
|
|
24304
|
-
|
|
24305
|
-
|
|
24306
|
-
|
|
24307
|
-
|
|
24308
|
-
const
|
|
24309
|
-
|
|
24310
|
-
|
|
24311
|
-
|
|
24312
|
-
|
|
24313
|
-
|
|
24314
|
-
|
|
24315
|
-
|
|
24316
|
-
|
|
24657
|
+
const pendingEmbeddings = /* @__PURE__ */ new Map();
|
|
24658
|
+
let embeddingActive = false;
|
|
24659
|
+
const drainEmbeddings = async () => {
|
|
24660
|
+
try {
|
|
24661
|
+
while (pendingEmbeddings.size) {
|
|
24662
|
+
const batch = /* @__PURE__ */ new Map();
|
|
24663
|
+
for (const [id2, content] of pendingEmbeddings) {
|
|
24664
|
+
pendingEmbeddings.delete(id2);
|
|
24665
|
+
batch.set(id2, content);
|
|
24666
|
+
if (batch.size === MAX_BATCH) break;
|
|
24667
|
+
}
|
|
24668
|
+
try {
|
|
24669
|
+
const vectors = await generateEmbeddings([...batch.values()], embeddingOptions);
|
|
24670
|
+
const embeddings2 = /* @__PURE__ */ new Map();
|
|
24671
|
+
[...batch.keys()].forEach((id2, i) => {
|
|
24672
|
+
try {
|
|
24673
|
+
embeddings2.set(id2, storedVector(vectors[i]));
|
|
24674
|
+
} catch (error) {
|
|
24675
|
+
getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
|
|
24676
|
+
}
|
|
24677
|
+
});
|
|
24678
|
+
if (!embeddings2.size) continue;
|
|
24679
|
+
const { failed } = await mutateMany(
|
|
24680
|
+
[...embeddings2.keys()],
|
|
24681
|
+
() => "embedding",
|
|
24682
|
+
(memory) => memory.content !== batch.get(memory.memory_id) || memory.embedding?.length ? null : {
|
|
24683
|
+
...memory,
|
|
24684
|
+
embedding: embeddings2.get(memory.memory_id),
|
|
24685
|
+
embedding_model: model
|
|
24686
|
+
},
|
|
24687
|
+
void 0,
|
|
24688
|
+
void 0,
|
|
24689
|
+
true
|
|
24690
|
+
);
|
|
24691
|
+
for (const error of failed.values())
|
|
24692
|
+
getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
|
|
24693
|
+
} catch (error) {
|
|
24694
|
+
getLogger().warn("[memory/remote-store] Failed to embed memories:", error);
|
|
24695
|
+
}
|
|
24696
|
+
}
|
|
24697
|
+
} finally {
|
|
24698
|
+
embeddingActive = false;
|
|
24699
|
+
}
|
|
24700
|
+
};
|
|
24701
|
+
const embedInBackground = (records) => {
|
|
24702
|
+
for (const { memory } of records) pendingEmbeddings.set(memory.memory_id, memory.content);
|
|
24703
|
+
if (embeddingActive || !pendingEmbeddings.size) return;
|
|
24704
|
+
embeddingActive = true;
|
|
24705
|
+
void drainEmbeddings();
|
|
24317
24706
|
};
|
|
24318
24707
|
const newRow = (input) => {
|
|
24319
24708
|
const now = Date.now();
|
|
@@ -24347,9 +24736,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24347
24736
|
};
|
|
24348
24737
|
};
|
|
24349
24738
|
const created = (records, inputs) => {
|
|
24350
|
-
records.
|
|
24351
|
-
if (inputs[i].embedding === void 0) embedInBackground(record2);
|
|
24352
|
-
});
|
|
24739
|
+
embedInBackground(records.filter((_, i) => inputs[i].embedding === void 0));
|
|
24353
24740
|
notify("membership", records);
|
|
24354
24741
|
return records.map((record2) => stored(record2.memory));
|
|
24355
24742
|
};
|
|
@@ -24379,7 +24766,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24379
24766
|
};
|
|
24380
24767
|
};
|
|
24381
24768
|
const withKnownKinds = async (topics) => topics.map(await knownKinds(topics));
|
|
24382
|
-
const readEveryState = async (ids, signal) => {
|
|
24769
|
+
const readEveryState = async (ids, signal, includeEmbeddings = false) => {
|
|
24383
24770
|
const records = /* @__PURE__ */ new Map();
|
|
24384
24771
|
const unreadable = /* @__PURE__ */ new Set();
|
|
24385
24772
|
for (const memory_ids of chunks2(ids, MAX_QUERY_IDS)) {
|
|
@@ -24391,6 +24778,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24391
24778
|
include_archived: true,
|
|
24392
24779
|
include_quarantined: true,
|
|
24393
24780
|
include_superseded: true,
|
|
24781
|
+
...includeEmbeddings && { include_embeddings: true },
|
|
24394
24782
|
limit: 200,
|
|
24395
24783
|
...signal && { signal },
|
|
24396
24784
|
...cursor2 && { cursor: cursor2 }
|
|
@@ -25053,7 +25441,7 @@ function createRemoteMemoryStore(options) {
|
|
|
25053
25441
|
}
|
|
25054
25442
|
return memory;
|
|
25055
25443
|
});
|
|
25056
|
-
if (saved && patch.embedding === void 0) embedInBackground(saved);
|
|
25444
|
+
if (saved && patch.embedding === void 0) embedInBackground([saved]);
|
|
25057
25445
|
return asStored(saved);
|
|
25058
25446
|
},
|
|
25059
25447
|
delete: async (id2) => !!await mutate(id2, "membership", (memory) => ({ ...memory, is_deleted: true })),
|
|
@@ -32341,6 +32729,7 @@ export {
|
|
|
32341
32729
|
createSelectPaymentWalletTool,
|
|
32342
32730
|
createStockPricePreProcessor,
|
|
32343
32731
|
createStreamingDeAnonymizer,
|
|
32732
|
+
createVaultAttachments,
|
|
32344
32733
|
createVaultChatBackend,
|
|
32345
32734
|
createVaultEmbeddingCache,
|
|
32346
32735
|
createVaultFolderOp,
|
|
@@ -32405,9 +32794,11 @@ export {
|
|
|
32405
32794
|
isRerankerAvailable,
|
|
32406
32795
|
localChatBackend,
|
|
32407
32796
|
maskScopedEmbeddingCache,
|
|
32797
|
+
maxVaultAttachmentBytes,
|
|
32408
32798
|
memoryCipher,
|
|
32409
32799
|
migrateChatsToRemote,
|
|
32410
32800
|
migrateMemoriesToRemote,
|
|
32801
|
+
migrateMessageAttachments,
|
|
32411
32802
|
moveMemoriesToFolderOp,
|
|
32412
32803
|
noopLogger,
|
|
32413
32804
|
onKeyAvailable,
|
|
@@ -32461,6 +32852,7 @@ export {
|
|
|
32461
32852
|
useCredits,
|
|
32462
32853
|
useEncryption,
|
|
32463
32854
|
useModels,
|
|
32855
|
+
vaultAttachmentRefs,
|
|
32464
32856
|
vaultChatBackend,
|
|
32465
32857
|
verifyMemoriesForPublish,
|
|
32466
32858
|
xhrTransport
|