@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.
@@ -12423,6 +12423,360 @@ async function migrateChatsToRemote(options) {
12423
12423
  return passes(false);
12424
12424
  }
12425
12425
 
12426
+ // src/lib/chatStore/vaultAttachments.ts
12427
+ var frameVersion = 1;
12428
+ var ivBytes = 12;
12429
+ var tagBytes = 16;
12430
+ var frameOverhead = 1 + ivBytes + tagBytes;
12431
+ var maxCiphertextBytes = 50 * 1024 * 1024;
12432
+ var expirySkewMs = 3e4;
12433
+ var maxRetryAfterMs = 3e4;
12434
+ var maxRefWrites = 5;
12435
+ var uploadWindowMs = 16 * 6e4;
12436
+ var attachmentIdPattern2 = /^[0-9a-f]{32}$/;
12437
+ var maxVaultAttachmentBytes = maxCiphertextBytes - frameOverhead;
12438
+ function additionalData(attachmentId) {
12439
+ return new TextEncoder().encode(`anuma-chat-attachment-v1:${attachmentId}`);
12440
+ }
12441
+ function invalidAttachment() {
12442
+ throw new ChatStoreError("Attachment does not decrypt under this key", 0, "invalid_attachment");
12443
+ }
12444
+ function sendableHeaders(headers) {
12445
+ return Object.fromEntries(
12446
+ Object.entries(headers).filter(([name]) => name.toLowerCase() !== "content-length")
12447
+ );
12448
+ }
12449
+ function transientStatus(status) {
12450
+ return status === 429 || status >= 500;
12451
+ }
12452
+ async function discardBody(response) {
12453
+ await response.body?.cancel().catch(() => void 0);
12454
+ }
12455
+ function createVaultAttachments(options) {
12456
+ const { store, keyRing, cache } = options;
12457
+ const fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);
12458
+ const retries = options.retries ?? 3;
12459
+ const retryDelayMs = options.retryDelayMs ?? 500;
12460
+ const now = options.now ?? Date.now;
12461
+ const sleep3 = (ms2, signal) => new Promise((resolve, reject) => {
12462
+ signal?.throwIfAborted();
12463
+ const timer = setTimeout(() => {
12464
+ signal?.removeEventListener("abort", onAbort);
12465
+ resolve();
12466
+ }, ms2);
12467
+ const onAbort = () => {
12468
+ clearTimeout(timer);
12469
+ reject(signal?.reason);
12470
+ };
12471
+ signal?.addEventListener("abort", onAbort, { once: true });
12472
+ });
12473
+ const pause = (attempt, signal, atLeast = 0) => sleep3(Math.max(atLeast, retryDelayMs * 2 ** attempt), signal);
12474
+ const withRetry = async (call, signal) => {
12475
+ for (let attempt = 0; ; attempt++) {
12476
+ try {
12477
+ return await call();
12478
+ } catch (error) {
12479
+ if (!(error instanceof ChatStoreError) || !transientStatus(error.status) || attempt >= retries || (error.retryAfterMs ?? 0) > maxRetryAfterMs)
12480
+ throw error;
12481
+ await pause(attempt, signal, error.retryAfterMs);
12482
+ }
12483
+ }
12484
+ };
12485
+ const expired = (url) => now() >= Date.parse(url.expiresAt) - expirySkewMs;
12486
+ const seal = async (bytes4, attachmentId) => {
12487
+ const iv = crypto.getRandomValues(new Uint8Array(ivBytes));
12488
+ const sealed2 = new Uint8Array(
12489
+ await crypto.subtle.encrypt(
12490
+ { name: "AES-GCM", iv, additionalData: additionalData(attachmentId) },
12491
+ keyRing.v3,
12492
+ bytes4
12493
+ )
12494
+ );
12495
+ const frame = new Uint8Array(1 + ivBytes + sealed2.length);
12496
+ frame[0] = frameVersion;
12497
+ frame.set(iv, 1);
12498
+ frame.set(sealed2, 1 + ivBytes);
12499
+ return frame;
12500
+ };
12501
+ const open = async (frame, attachmentId) => {
12502
+ if (frame.length < frameOverhead || frame[0] !== frameVersion) invalidAttachment();
12503
+ try {
12504
+ return new Uint8Array(
12505
+ await crypto.subtle.decrypt(
12506
+ {
12507
+ name: "AES-GCM",
12508
+ iv: frame.slice(1, 1 + ivBytes),
12509
+ additionalData: additionalData(attachmentId)
12510
+ },
12511
+ keyRing.v3,
12512
+ frame.slice(1 + ivBytes)
12513
+ )
12514
+ );
12515
+ } catch {
12516
+ return invalidAttachment();
12517
+ }
12518
+ };
12519
+ const put = async (upload, body, signal) => {
12520
+ for (let attempt = 0; ; attempt++) {
12521
+ if (expired(upload)) return "expired";
12522
+ let response;
12523
+ try {
12524
+ response = await fetcher(upload.url, {
12525
+ method: upload.method,
12526
+ headers: sendableHeaders(upload.headers),
12527
+ body,
12528
+ signal
12529
+ });
12530
+ } catch (error) {
12531
+ if (signal?.aborted || attempt >= retries) throw error;
12532
+ await pause(attempt, signal);
12533
+ continue;
12534
+ }
12535
+ await discardBody(response);
12536
+ if (response.ok) return "stored";
12537
+ if (response.status === 403) return "expired";
12538
+ if (!transientStatus(response.status) || attempt >= retries)
12539
+ throw new ChatStoreError(
12540
+ `Attachment upload failed with ${response.status}`,
12541
+ response.status,
12542
+ "attachment_upload_failed"
12543
+ );
12544
+ await pause(attempt, signal);
12545
+ }
12546
+ };
12547
+ const download = async (url, signal) => {
12548
+ for (let attempt = 0; ; attempt++) {
12549
+ if (expired(url)) return "expired";
12550
+ let response;
12551
+ try {
12552
+ response = await fetcher(url.url, {
12553
+ method: url.method,
12554
+ headers: sendableHeaders(url.headers),
12555
+ signal
12556
+ });
12557
+ if (response.ok) return new Uint8Array(await response.arrayBuffer());
12558
+ } catch (error) {
12559
+ if (signal?.aborted || attempt >= retries) throw error;
12560
+ await pause(attempt, signal);
12561
+ continue;
12562
+ }
12563
+ await discardBody(response);
12564
+ if (response.status === 403) return "expired";
12565
+ if (response.status === 404) return "missing";
12566
+ if (!transientStatus(response.status) || attempt >= retries)
12567
+ throw new ChatStoreError(
12568
+ `Attachment download failed with ${response.status}`,
12569
+ response.status,
12570
+ "attachment_download_failed"
12571
+ );
12572
+ await pause(attempt, signal);
12573
+ }
12574
+ };
12575
+ const remove = async (attachmentId, signal) => {
12576
+ try {
12577
+ await withRetry(() => store.attachments.delete(attachmentId, signal), signal);
12578
+ } catch (error) {
12579
+ if (!(error instanceof ChatStoreError) || error.status !== 404) throw error;
12580
+ }
12581
+ await cache?.delete(attachmentId).catch(() => void 0);
12582
+ };
12583
+ const discardPending = async (attachmentId) => {
12584
+ const found = await store.attachments.get(attachmentId);
12585
+ if (found?.attachment.state === "pending") await remove(attachmentId);
12586
+ };
12587
+ return {
12588
+ async upload(bytes4, uploadOptions) {
12589
+ const signal = uploadOptions?.signal;
12590
+ if (!(bytes4 instanceof Uint8Array) || bytes4.length > maxVaultAttachmentBytes)
12591
+ throw new ChatStoreError(
12592
+ "Attachment is larger than vault accepts",
12593
+ 413,
12594
+ "attachment_too_large"
12595
+ );
12596
+ const size = bytes4.length + frameOverhead;
12597
+ for (let attempt = 0; ; attempt++) {
12598
+ const { attachment: attachment2, upload } = await withRetry(
12599
+ () => store.attachments.create(size, signal),
12600
+ signal
12601
+ );
12602
+ try {
12603
+ await uploadOptions?.onReserved?.(attachment2.id);
12604
+ const frame = await seal(bytes4, attachment2.id);
12605
+ if (await put(upload, frame, signal) === "stored") return attachment2.id;
12606
+ } catch (error) {
12607
+ await discardPending(attachment2.id).catch(() => void 0);
12608
+ throw error;
12609
+ }
12610
+ await remove(attachment2.id).catch(() => void 0);
12611
+ if (attempt >= retries)
12612
+ throw new ChatStoreError(
12613
+ "Attachment storage rejected the upload URL",
12614
+ 403,
12615
+ "attachment_upload_rejected"
12616
+ );
12617
+ }
12618
+ },
12619
+ commit(attachmentId, owner, signal) {
12620
+ return withRetry(() => store.attachments.commit(attachmentId, owner, signal), signal);
12621
+ },
12622
+ async read(attachmentId, signal) {
12623
+ if (!attachmentIdPattern2.test(attachmentId)) invalidAttachment();
12624
+ const cached = await cache?.get(attachmentId).catch(() => null);
12625
+ if (cached) return cached;
12626
+ for (let attempt = 0; ; attempt++) {
12627
+ const found = await withRetry(() => store.attachments.get(attachmentId, signal), signal);
12628
+ if (!found?.download) return null;
12629
+ const frame = await download(found.download, signal);
12630
+ if (frame === "missing") return null;
12631
+ if (frame === "expired") {
12632
+ if (attempt >= retries)
12633
+ throw new ChatStoreError(
12634
+ "Attachment storage rejected the download URL",
12635
+ 403,
12636
+ "attachment_download_rejected"
12637
+ );
12638
+ continue;
12639
+ }
12640
+ if (frame.length !== found.attachment.sizeBytes) invalidAttachment();
12641
+ const bytes4 = await open(frame, attachmentId);
12642
+ await cache?.set(attachmentId, bytes4).catch(() => void 0);
12643
+ return bytes4;
12644
+ }
12645
+ },
12646
+ delete: remove
12647
+ };
12648
+ }
12649
+ function validRef(value) {
12650
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
12651
+ const ref3 = value;
12652
+ 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;
12653
+ }
12654
+ function vaultAttachmentRefs(record2) {
12655
+ const refs = record2.data.vaultAttachments;
12656
+ return Array.isArray(refs) ? refs.filter(validRef) : [];
12657
+ }
12658
+ function journalKey(messageId, fileId) {
12659
+ return JSON.stringify([messageId, fileId]);
12660
+ }
12661
+ async function migrateMessageAttachments(options) {
12662
+ const { store, attachments, journal, messageId, signal } = options;
12663
+ const now = options.now ?? Date.now;
12664
+ const owner = { kind: "message", id: messageId };
12665
+ const ownerGone = () => new ChatStoreError("Message is not in vault", 409, "attachment_owner_not_found");
12666
+ let snapshot = await store.get("message", messageId, signal);
12667
+ if (!snapshot || snapshot.record.isDeleted) throw ownerGone();
12668
+ const present = new Map(vaultAttachmentRefs(snapshot.record).map((r) => [r.fileId, r]));
12669
+ const uploadable = (attachment2) => attachment2.state === "pending" && now() < Date.parse(attachment2.createdAt) + uploadWindowMs;
12670
+ const lookup = async (attachmentId) => attachmentId && attachmentIdPattern2.test(attachmentId) ? (await store.attachments.get(attachmentId, signal))?.attachment ?? null : null;
12671
+ const bind = async (found) => {
12672
+ if (!found) return null;
12673
+ if (found.state === "committed")
12674
+ return found.ownerKind === owner.kind && found.ownerId === owner.id ? found : null;
12675
+ try {
12676
+ return await attachments.commit(found.id, owner, signal);
12677
+ } catch (error) {
12678
+ if (!(error instanceof ChatStoreError) || error.code !== "attachment_not_uploaded")
12679
+ throw error;
12680
+ if (uploadable(found)) return "busy";
12681
+ await attachments.delete(found.id, signal);
12682
+ return null;
12683
+ }
12684
+ };
12685
+ const added = [];
12686
+ const settled = [];
12687
+ const missing2 = [];
12688
+ const oversized = [];
12689
+ const deferred = [];
12690
+ const stale = /* @__PURE__ */ new Set();
12691
+ let uploaded = 0;
12692
+ for (const file of options.files) {
12693
+ signal?.throwIfAborted();
12694
+ const key3 = journalKey(messageId, file.fileId);
12695
+ const recorded = present.get(file.fileId);
12696
+ if (recorded) {
12697
+ const bound = await bind(await lookup(recorded.attachmentId));
12698
+ if (bound === "busy") {
12699
+ deferred.push(file.fileId);
12700
+ continue;
12701
+ }
12702
+ if (bound) {
12703
+ const stray = await lookup(await journal.get(key3));
12704
+ if (stray && stray.id !== recorded.attachmentId) {
12705
+ if (uploadable(stray)) continue;
12706
+ await attachments.delete(stray.id, signal);
12707
+ }
12708
+ settled.push(key3);
12709
+ continue;
12710
+ }
12711
+ stale.add(recorded.attachmentId);
12712
+ }
12713
+ const meta = { fileId: file.fileId, name: file.name, type: file.type };
12714
+ const resumed = await bind(await lookup(await journal.get(key3)));
12715
+ if (resumed === "busy") {
12716
+ deferred.push(file.fileId);
12717
+ continue;
12718
+ }
12719
+ if (resumed) {
12720
+ added.push({ attachmentId: resumed.id, ...meta, size: resumed.sizeBytes - frameOverhead });
12721
+ settled.push(key3);
12722
+ continue;
12723
+ }
12724
+ const bytes4 = await file.read();
12725
+ if (!bytes4) {
12726
+ missing2.push(file.fileId);
12727
+ continue;
12728
+ }
12729
+ if (bytes4.length > maxVaultAttachmentBytes) {
12730
+ oversized.push(file.fileId);
12731
+ continue;
12732
+ }
12733
+ const attachmentId = await attachments.upload(bytes4, {
12734
+ signal,
12735
+ onReserved: (id2) => journal.set(key3, id2)
12736
+ });
12737
+ uploaded++;
12738
+ await attachments.commit(attachmentId, owner, signal);
12739
+ added.push({ attachmentId, ...meta, size: bytes4.length });
12740
+ settled.push(key3);
12741
+ }
12742
+ const superseded = [];
12743
+ for (let attempt = 0; added.length > 0; attempt++) {
12744
+ const refs = new Map(vaultAttachmentRefs(snapshot.record).map((r) => [r.fileId, r]));
12745
+ superseded.length = 0;
12746
+ for (const ref3 of added) {
12747
+ const prior = refs.get(ref3.fileId);
12748
+ if (prior && prior.attachmentId !== ref3.attachmentId && !stale.has(prior.attachmentId))
12749
+ superseded.push(ref3.attachmentId);
12750
+ else refs.set(ref3.fileId, ref3);
12751
+ }
12752
+ if (superseded.length === added.length) break;
12753
+ try {
12754
+ [snapshot] = await store.putMany(
12755
+ [
12756
+ {
12757
+ record: {
12758
+ ...snapshot.record,
12759
+ data: { ...snapshot.record.data, ...plain({ vaultAttachments: [...refs.values()] }) }
12760
+ },
12761
+ expectedVersion: snapshot.version
12762
+ }
12763
+ ],
12764
+ signal
12765
+ );
12766
+ break;
12767
+ } catch (error) {
12768
+ if (!(error instanceof ChatStoreError) || error.code !== "version_conflict" || attempt + 1 >= maxRefWrites)
12769
+ throw error;
12770
+ const latest = await store.get("message", messageId, signal);
12771
+ if (!latest || latest.record.isDeleted) throw ownerGone();
12772
+ snapshot = latest;
12773
+ }
12774
+ }
12775
+ for (const id2 of superseded) await attachments.delete(id2, signal);
12776
+ for (const key3 of settled) await journal.set(key3, null);
12777
+ return { refs: vaultAttachmentRefs(snapshot.record), uploaded, missing: missing2, oversized, deferred };
12778
+ }
12779
+
12426
12780
  // src/lib/chatStore/vaultBackend.ts
12427
12781
  import { v7 as uuidv73 } from "uuid";
12428
12782
 
@@ -12562,6 +12916,7 @@ var resumableFields = [
12562
12916
  "imageModel",
12563
12917
  "files",
12564
12918
  "fileIds",
12919
+ "vaultAttachments",
12565
12920
  "usage",
12566
12921
  "sources",
12567
12922
  "responseDuration",
@@ -26353,7 +26708,7 @@ function createRemoteMemoryStore(options) {
26353
26708
  };
26354
26709
  const mutate = (id2, change, edit, writeOptions) => serialized(id2, () => mutateLocked(id2, change, edit, writeOptions));
26355
26710
  const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id2) => () => serialized(id2, inner), task)();
26356
- const mutateMany = async (ids, change, edit, leaseToken, signal) => {
26711
+ const mutateMany = async (ids, change, edit, leaseToken, signal, includeEmbeddings = false) => {
26357
26712
  const saved = /* @__PURE__ */ new Map();
26358
26713
  const failed = /* @__PURE__ */ new Map();
26359
26714
  for (const slice of chunks2([...new Set(ids)], MAX_BATCH)) {
@@ -26362,7 +26717,7 @@ function createRemoteMemoryStore(options) {
26362
26717
  const writes = [];
26363
26718
  let read;
26364
26719
  try {
26365
- read = await readEveryState(slice, signal);
26720
+ read = await readEveryState(slice, signal, includeEmbeddings);
26366
26721
  } catch (error) {
26367
26722
  signal?.throwIfAborted();
26368
26723
  for (const id2 of slice) failed.set(id2, error);
@@ -26421,21 +26776,55 @@ function createRemoteMemoryStore(options) {
26421
26776
  }
26422
26777
  return { saved, failed };
26423
26778
  };
26424
- const embedInBackground = ({ memory: { memory_id: id2, content } }) => {
26425
- generateEmbedding(content, embeddingOptions).then(
26426
- (vector2) => serialized(id2, async () => {
26427
- const current = await live(id2);
26428
- if (!current || current.memory.content !== content || current.memory.embedding?.length)
26429
- return;
26430
- const saved = await persistence.put(
26431
- { ...current.memory, embedding: storedVector(vector2), embedding_model: model },
26432
- current
26433
- );
26434
- notify("embedding", [saved]);
26435
- })
26436
- ).catch((error) => {
26437
- getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
26438
- });
26779
+ const pendingEmbeddings = /* @__PURE__ */ new Map();
26780
+ let embeddingActive = false;
26781
+ const drainEmbeddings = async () => {
26782
+ try {
26783
+ while (pendingEmbeddings.size) {
26784
+ const batch = /* @__PURE__ */ new Map();
26785
+ for (const [id2, content] of pendingEmbeddings) {
26786
+ pendingEmbeddings.delete(id2);
26787
+ batch.set(id2, content);
26788
+ if (batch.size === MAX_BATCH) break;
26789
+ }
26790
+ try {
26791
+ const vectors = await generateEmbeddings([...batch.values()], embeddingOptions);
26792
+ const embeddings2 = /* @__PURE__ */ new Map();
26793
+ [...batch.keys()].forEach((id2, i) => {
26794
+ try {
26795
+ embeddings2.set(id2, storedVector(vectors[i]));
26796
+ } catch (error) {
26797
+ getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
26798
+ }
26799
+ });
26800
+ if (!embeddings2.size) continue;
26801
+ const { failed } = await mutateMany(
26802
+ [...embeddings2.keys()],
26803
+ () => "embedding",
26804
+ (memory) => memory.content !== batch.get(memory.memory_id) || memory.embedding?.length ? null : {
26805
+ ...memory,
26806
+ embedding: embeddings2.get(memory.memory_id),
26807
+ embedding_model: model
26808
+ },
26809
+ void 0,
26810
+ void 0,
26811
+ true
26812
+ );
26813
+ for (const error of failed.values())
26814
+ getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
26815
+ } catch (error) {
26816
+ getLogger().warn("[memory/remote-store] Failed to embed memories:", error);
26817
+ }
26818
+ }
26819
+ } finally {
26820
+ embeddingActive = false;
26821
+ }
26822
+ };
26823
+ const embedInBackground = (records) => {
26824
+ for (const { memory } of records) pendingEmbeddings.set(memory.memory_id, memory.content);
26825
+ if (embeddingActive || !pendingEmbeddings.size) return;
26826
+ embeddingActive = true;
26827
+ void drainEmbeddings();
26439
26828
  };
26440
26829
  const newRow = (input) => {
26441
26830
  const now = Date.now();
@@ -26469,9 +26858,7 @@ function createRemoteMemoryStore(options) {
26469
26858
  };
26470
26859
  };
26471
26860
  const created = (records, inputs) => {
26472
- records.forEach((record2, i) => {
26473
- if (inputs[i].embedding === void 0) embedInBackground(record2);
26474
- });
26861
+ embedInBackground(records.filter((_, i) => inputs[i].embedding === void 0));
26475
26862
  notify("membership", records);
26476
26863
  return records.map((record2) => stored(record2.memory));
26477
26864
  };
@@ -26501,7 +26888,7 @@ function createRemoteMemoryStore(options) {
26501
26888
  };
26502
26889
  };
26503
26890
  const withKnownKinds = async (topics) => topics.map(await knownKinds(topics));
26504
- const readEveryState = async (ids, signal) => {
26891
+ const readEveryState = async (ids, signal, includeEmbeddings = false) => {
26505
26892
  const records = /* @__PURE__ */ new Map();
26506
26893
  const unreadable = /* @__PURE__ */ new Set();
26507
26894
  for (const memory_ids of chunks2(ids, MAX_QUERY_IDS)) {
@@ -26513,6 +26900,7 @@ function createRemoteMemoryStore(options) {
26513
26900
  include_archived: true,
26514
26901
  include_quarantined: true,
26515
26902
  include_superseded: true,
26903
+ ...includeEmbeddings && { include_embeddings: true },
26516
26904
  limit: 200,
26517
26905
  ...signal && { signal },
26518
26906
  ...cursor2 && { cursor: cursor2 }
@@ -27175,7 +27563,7 @@ function createRemoteMemoryStore(options) {
27175
27563
  }
27176
27564
  return memory;
27177
27565
  });
27178
- if (saved && patch.embedding === void 0) embedInBackground(saved);
27566
+ if (saved && patch.embedding === void 0) embedInBackground([saved]);
27179
27567
  return asStored(saved);
27180
27568
  },
27181
27569
  delete: async (id2) => !!await mutate(id2, "membership", (memory) => ({ ...memory, is_deleted: true })),
@@ -40212,6 +40600,7 @@ export {
40212
40600
  createSelectPaymentWalletTool,
40213
40601
  createServerToolsFilter,
40214
40602
  createStockPricePreProcessor,
40603
+ createVaultAttachments,
40215
40604
  createVaultChatBackend,
40216
40605
  createVaultEmbeddingCache,
40217
40606
  createVaultFolderOp,
@@ -40361,11 +40750,13 @@ export {
40361
40750
  linkMemoryEntitiesOp,
40362
40751
  localChatBackend,
40363
40752
  maskScopedEmbeddingCache,
40753
+ maxVaultAttachmentBytes,
40364
40754
  mediaToStored,
40365
40755
  memoryCipher,
40366
40756
  migrateChatsToRemote,
40367
40757
  migrateDisplayResult,
40368
40758
  migrateMemoriesToRemote,
40759
+ migrateMessageAttachments,
40369
40760
  migrateNotionClientRegistration,
40370
40761
  migrateNotionToken,
40371
40762
  moveMemoriesToFolderOp,
@@ -40474,6 +40865,7 @@ export {
40474
40865
  useVoice,
40475
40866
  useWalletBinding,
40476
40867
  userPreferencesStorageSchema,
40868
+ vaultAttachmentRefs,
40477
40869
  vaultChatBackend,
40478
40870
  verifyMemoriesForPublish,
40479
40871
  walk,
@@ -7389,6 +7389,14 @@ interface FileMetadata {
7389
7389
  */
7390
7390
  sourceUrl?: string;
7391
7391
  }
7392
+ /** Points a message's local file (`FileMetadata.id` or a `fileIds` media id) at its encrypted copy in vault, so any device can fetch it. */
7393
+ interface VaultAttachmentRef {
7394
+ attachmentId: string;
7395
+ fileId: string;
7396
+ name: string;
7397
+ type: string;
7398
+ size: number;
7399
+ }
7392
7400
  interface ChatCompletionUsage {
7393
7401
  promptTokens?: number;
7394
7402
  completionTokens?: number;
@@ -7492,6 +7500,7 @@ interface StoredMessage {
7492
7500
  files?: FileMetadata[];
7493
7501
  /** Array of media_id references for direct lookup in media table */
7494
7502
  fileIds?: string[];
7503
+ vaultAttachments?: VaultAttachmentRef[];
7495
7504
  createdAt: Date;
7496
7505
  updatedAt: Date;
7497
7506
  vector?: number[];
@@ -7668,6 +7677,7 @@ interface CreateMessageOptions {
7668
7677
  files?: FileMetadata[];
7669
7678
  /** Array of media_id references for direct lookup in media table */
7670
7679
  fileIds?: string[];
7680
+ vaultAttachments?: VaultAttachmentRef[];
7671
7681
  usage?: ChatCompletionUsage;
7672
7682
  sources?: SearchSource[];
7673
7683
  responseDuration?: number;
@@ -7389,6 +7389,14 @@ interface FileMetadata {
7389
7389
  */
7390
7390
  sourceUrl?: string;
7391
7391
  }
7392
+ /** Points a message's local file (`FileMetadata.id` or a `fileIds` media id) at its encrypted copy in vault, so any device can fetch it. */
7393
+ interface VaultAttachmentRef {
7394
+ attachmentId: string;
7395
+ fileId: string;
7396
+ name: string;
7397
+ type: string;
7398
+ size: number;
7399
+ }
7392
7400
  interface ChatCompletionUsage {
7393
7401
  promptTokens?: number;
7394
7402
  completionTokens?: number;
@@ -7492,6 +7500,7 @@ interface StoredMessage {
7492
7500
  files?: FileMetadata[];
7493
7501
  /** Array of media_id references for direct lookup in media table */
7494
7502
  fileIds?: string[];
7503
+ vaultAttachments?: VaultAttachmentRef[];
7495
7504
  createdAt: Date;
7496
7505
  updatedAt: Date;
7497
7506
  vector?: number[];
@@ -7668,6 +7677,7 @@ interface CreateMessageOptions {
7668
7677
  files?: FileMetadata[];
7669
7678
  /** Array of media_id references for direct lookup in media table */
7670
7679
  fileIds?: string[];
7680
+ vaultAttachments?: VaultAttachmentRef[];
7671
7681
  usage?: ChatCompletionUsage;
7672
7682
  sources?: SearchSource[];
7673
7683
  responseDuration?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "10.3.0",
3
+ "version": "10.4.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",