@anuma/sdk 10.0.1 → 10.0.3

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.
@@ -1674,6 +1674,160 @@ async function assembleDecryptedMessage(message, address) {
1674
1674
  return result;
1675
1675
  }
1676
1676
 
1677
+ // src/lib/db/chat/models.ts
1678
+ import { Model as Model2 } from "@nozbe/watermelondb";
1679
+ import { date, field, json, text } from "@nozbe/watermelondb/decorators";
1680
+ var Message = class extends Model2 {
1681
+ };
1682
+ Message.table = "history";
1683
+ Message.associations = {
1684
+ conversations: { type: "belongs_to", key: "conversation_id" },
1685
+ media: { type: "has_many", foreignKey: "message_id" }
1686
+ };
1687
+ __decorateClass([
1688
+ field("message_id")
1689
+ ], Message.prototype, "messageId", 2);
1690
+ __decorateClass([
1691
+ text("conversation_id")
1692
+ ], Message.prototype, "conversationId", 2);
1693
+ __decorateClass([
1694
+ text("role")
1695
+ ], Message.prototype, "role", 2);
1696
+ __decorateClass([
1697
+ text("content")
1698
+ ], Message.prototype, "content", 2);
1699
+ __decorateClass([
1700
+ text("model")
1701
+ ], Message.prototype, "model", 2);
1702
+ __decorateClass([
1703
+ text("image_model")
1704
+ ], Message.prototype, "imageModel", 2);
1705
+ __decorateClass([
1706
+ json("files", (raw) => raw)
1707
+ ], Message.prototype, "files", 2);
1708
+ __decorateClass([
1709
+ json("file_ids", (raw) => raw)
1710
+ ], Message.prototype, "fileIds", 2);
1711
+ __decorateClass([
1712
+ date("created_at")
1713
+ ], Message.prototype, "createdAt", 2);
1714
+ __decorateClass([
1715
+ date("updated_at")
1716
+ ], Message.prototype, "updatedAt", 2);
1717
+ __decorateClass([
1718
+ json("vector", (raw) => raw)
1719
+ ], Message.prototype, "vector", 2);
1720
+ __decorateClass([
1721
+ text("embedding_model")
1722
+ ], Message.prototype, "embeddingModel", 2);
1723
+ __decorateClass([
1724
+ json("chunks", (raw) => raw)
1725
+ ], Message.prototype, "chunks", 2);
1726
+ __decorateClass([
1727
+ json("usage", (raw) => raw)
1728
+ ], Message.prototype, "usage", 2);
1729
+ __decorateClass([
1730
+ json("sources", (raw) => raw)
1731
+ ], Message.prototype, "sources", 2);
1732
+ __decorateClass([
1733
+ field("response_duration")
1734
+ ], Message.prototype, "responseDuration", 2);
1735
+ __decorateClass([
1736
+ field("was_stopped")
1737
+ ], Message.prototype, "wasStopped", 2);
1738
+ __decorateClass([
1739
+ text("error")
1740
+ ], Message.prototype, "error", 2);
1741
+ __decorateClass([
1742
+ json("thought_process", (raw) => raw)
1743
+ ], Message.prototype, "thoughtProcess", 2);
1744
+ __decorateClass([
1745
+ text("thinking")
1746
+ ], Message.prototype, "thinking", 2);
1747
+ __decorateClass([
1748
+ text("parent_message_id")
1749
+ ], Message.prototype, "parentMessageId", 2);
1750
+ __decorateClass([
1751
+ text("feedback")
1752
+ ], Message.prototype, "feedback", 2);
1753
+ __decorateClass([
1754
+ json("tool_call_events", (raw) => raw)
1755
+ ], Message.prototype, "toolCallEvents", 2);
1756
+ __decorateClass([
1757
+ text("origin")
1758
+ ], Message.prototype, "origin", 2);
1759
+ var Conversation = class extends Model2 {
1760
+ };
1761
+ Conversation.table = "conversations";
1762
+ Conversation.associations = {
1763
+ history: { type: "has_many", foreignKey: "conversation_id" },
1764
+ projects: { type: "belongs_to", key: "project_id" }
1765
+ };
1766
+ __decorateClass([
1767
+ text("conversation_id")
1768
+ ], Conversation.prototype, "conversationId", 2);
1769
+ __decorateClass([
1770
+ text("title")
1771
+ ], Conversation.prototype, "title", 2);
1772
+ __decorateClass([
1773
+ text("project_id")
1774
+ ], Conversation.prototype, "projectId", 2);
1775
+ __decorateClass([
1776
+ date("created_at")
1777
+ ], Conversation.prototype, "createdAt", 2);
1778
+ __decorateClass([
1779
+ date("updated_at")
1780
+ ], Conversation.prototype, "updatedAt", 2);
1781
+ __decorateClass([
1782
+ field("is_deleted")
1783
+ ], Conversation.prototype, "isDeleted", 2);
1784
+ __decorateClass([
1785
+ date("pinned_at")
1786
+ ], Conversation.prototype, "pinnedAt", 2);
1787
+ var ConversationSummary = class extends Model2 {
1788
+ };
1789
+ ConversationSummary.table = "conversation_summaries";
1790
+ ConversationSummary.associations = {
1791
+ conversations: { type: "belongs_to", key: "conversation_id" }
1792
+ };
1793
+ __decorateClass([
1794
+ text("conversation_id")
1795
+ ], ConversationSummary.prototype, "conversationId", 2);
1796
+ __decorateClass([
1797
+ text("summary")
1798
+ ], ConversationSummary.prototype, "summary", 2);
1799
+ __decorateClass([
1800
+ text("summarized_up_to")
1801
+ ], ConversationSummary.prototype, "summarizedUpTo", 2);
1802
+ __decorateClass([
1803
+ field("token_count")
1804
+ ], ConversationSummary.prototype, "tokenCount", 2);
1805
+ __decorateClass([
1806
+ date("created_at")
1807
+ ], ConversationSummary.prototype, "createdAt", 2);
1808
+ __decorateClass([
1809
+ date("updated_at")
1810
+ ], ConversationSummary.prototype, "updatedAt", 2);
1811
+
1812
+ // src/lib/db/chat/summaryRevision.ts
1813
+ var conversationRevisions = /* @__PURE__ */ new WeakMap();
1814
+ function getConversationRevision(database, conversationId) {
1815
+ return conversationRevisions.get(database)?.get(conversationId) ?? 0;
1816
+ }
1817
+ function advanceConversationRevision(database, conversationId) {
1818
+ let revisions = conversationRevisions.get(database);
1819
+ if (!revisions) {
1820
+ revisions = /* @__PURE__ */ new Map();
1821
+ conversationRevisions.set(database, revisions);
1822
+ }
1823
+ revisions.set(conversationId, getConversationRevision(database, conversationId) + 1);
1824
+ }
1825
+ function assertConversationRevision(database, conversationId, revision2) {
1826
+ if (getConversationRevision(database, conversationId) !== revision2) {
1827
+ throw new Error("The conversation changed during summarization. Retry the request.");
1828
+ }
1829
+ }
1830
+
1677
1831
  // src/lib/db/chat/toolCallEventIndex.ts
1678
1832
  import { Q } from "@nozbe/watermelondb";
1679
1833
  function parseEventIds(value) {
@@ -2359,8 +2513,20 @@ async function getMessageSkeletonsOp(ctx, convId) {
2359
2513
  async function getToolCallEventIdsOp(ctx, convId) {
2360
2514
  return getToolCallEventIds(ctx.messagesCollection, convId);
2361
2515
  }
2516
+ async function invalidateConversationSummary(ctx, conversationId, changedMessageId) {
2517
+ if (!ctx.database.schema?.tables[ConversationSummary.table]) return;
2518
+ const summaries = await ctx.database.get(ConversationSummary.table).query(Q2.where("conversation_id", conversationId)).fetch();
2519
+ for (const summary of summaries) {
2520
+ if (changedMessageId !== void 0) {
2521
+ const [boundary] = await ctx.messagesCollection.query(Q2.where("id", summary.summarizedUpTo), Q2.where("conversation_id", conversationId)).fetch();
2522
+ if (boundary && changedMessageId > boundary.messageId) continue;
2523
+ }
2524
+ await summary.destroyPermanently();
2525
+ }
2526
+ }
2362
2527
  async function clearMessagesOp(ctx, convId) {
2363
2528
  await ctx.database.write(async () => {
2529
+ await invalidateConversationSummary(ctx, convId);
2364
2530
  const messages = await ctx.messagesCollection.query(Q2.where("conversation_id", convId)).fetch();
2365
2531
  const jobs = ctx.database.schema?.tables[ExtractionJob.table] ? await ctx.database.get(ExtractionJob.table).query(Q2.where("conversation_id", convId)).fetch() : [];
2366
2532
  for (const job of jobs) {
@@ -2372,11 +2538,12 @@ async function clearMessagesOp(ctx, convId) {
2372
2538
  }
2373
2539
  for (const message of messages) {
2374
2540
  await message.update((msg) => {
2375
- msg._setRaw("file_ids", null);
2541
+ if (ctx.messagesCollection.schema.columns.file_ids) msg._setRaw("file_ids", null);
2376
2542
  msg._setRaw("files", null);
2377
2543
  });
2378
2544
  await message.destroyPermanently();
2379
2545
  }
2546
+ advanceConversationRevision(ctx.database, convId);
2380
2547
  });
2381
2548
  }
2382
2549
  async function deleteMessageOp(ctx, uniqueId) {
@@ -2387,6 +2554,7 @@ async function deleteMessageOp(ctx, uniqueId) {
2387
2554
  return null;
2388
2555
  }
2389
2556
  await ctx.database.write(async () => {
2557
+ await invalidateConversationSummary(ctx, message.conversationId, message.messageId);
2390
2558
  const jobs = ctx.database.schema?.tables[ExtractionJob.table] ? await ctx.database.get(ExtractionJob.table).query(Q2.where("conversation_id", message.conversationId)).fetch() : [];
2391
2559
  for (const job of jobs) {
2392
2560
  const ids = JSON.parse(String(job._getRaw("message_ids")));
@@ -2396,10 +2564,11 @@ async function deleteMessageOp(ctx, uniqueId) {
2396
2564
  });
2397
2565
  }
2398
2566
  await message.update((msg) => {
2399
- msg._setRaw("file_ids", null);
2567
+ if (ctx.messagesCollection.schema.columns.file_ids) msg._setRaw("file_ids", null);
2400
2568
  msg._setRaw("files", null);
2401
2569
  });
2402
2570
  await message.destroyPermanently();
2571
+ advanceConversationRevision(ctx.database, message.conversationId);
2403
2572
  });
2404
2573
  return uniqueId;
2405
2574
  }
@@ -2818,6 +2987,14 @@ async function _updateMessageOp(ctx, uniqueId, opts) {
2818
2987
  ctx.embeddedWalletSigner
2819
2988
  ) : opts;
2820
2989
  await ctx.database.write(async () => {
2990
+ let contentChanged = false;
2991
+ if (opts.content !== void 0) {
2992
+ const originalContent = ctx.walletAddress ? await decryptField(message.content, ctx.walletAddress) : message.content;
2993
+ contentChanged = opts.content !== originalContent;
2994
+ if (contentChanged) {
2995
+ await invalidateConversationSummary(ctx, message.conversationId, message.messageId);
2996
+ }
2997
+ }
2821
2998
  await message.update((msg) => {
2822
2999
  if (encryptedOpts.content !== void 0)
2823
3000
  msg._setRaw("content", encryptedOpts.content);
@@ -2862,6 +3039,7 @@ async function _updateMessageOp(ctx, uniqueId, opts) {
2862
3039
  msg._setRaw("tool_call_events", tceValue);
2863
3040
  }
2864
3041
  });
3042
+ if (contentChanged) advanceConversationRevision(ctx.database, message.conversationId);
2865
3043
  });
2866
3044
  return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
2867
3045
  }
@@ -4791,22 +4969,22 @@ function toReceipt(action, argumentsJson, output) {
4791
4969
  const result = parseObject(output);
4792
4970
  return {
4793
4971
  kind: action.kind,
4794
- venueName: text(args.venue_name) ?? "",
4795
- day: text(args.day) ?? "",
4796
- time: text(args.time) ?? "",
4972
+ venueName: text2(args.venue_name) ?? "",
4973
+ day: text2(args.day) ?? "",
4974
+ time: text2(args.time) ?? "",
4797
4975
  partySize: count(args.party_size),
4798
- reservationId: text(result.reservation_id) ?? text(args.reservation_id),
4799
- resyUrl: text(result.reservations_url),
4800
- feeSummary: text(result.fee_summary),
4976
+ reservationId: text2(result.reservation_id) ?? text2(args.reservation_id),
4977
+ resyUrl: text2(result.reservations_url),
4978
+ feeSummary: text2(result.fee_summary),
4801
4979
  ...outcome(action, output, result)
4802
4980
  };
4803
4981
  }
4804
4982
  function outcome(action, output, result) {
4805
4983
  if (action.alreadyDone.test(output)) return { status: "already_done" };
4806
- const reason = text(result.error);
4984
+ const reason = text2(result.error);
4807
4985
  if (action.kind === "booking") {
4808
4986
  if (BOOKING_OUTCOME_UNKNOWN.test(output)) return { status: "unknown" };
4809
- const held = result.success === true || text(result.reservation_id) !== void 0;
4987
+ const held = result.success === true || text2(result.reservation_id) !== void 0;
4810
4988
  return held ? { status: "made" } : { status: "not_made", reason };
4811
4989
  }
4812
4990
  if (result.error_code === CANCEL_OUTCOME_UNKNOWN) return { status: "unknown", reason };
@@ -4821,7 +4999,7 @@ function parseObject(json5) {
4821
4999
  return {};
4822
5000
  }
4823
5001
  }
4824
- function text(value) {
5002
+ function text2(value) {
4825
5003
  if (typeof value === "number") return String(value);
4826
5004
  return typeof value === "string" && value ? value : void 0;
4827
5005
  }
@@ -10288,7 +10466,7 @@ function hasControl(value) {
10288
10466
  function integer(value, minimum = 0) {
10289
10467
  return Number.isSafeInteger(value) && value >= minimum;
10290
10468
  }
10291
- function json(value, ancestors = /* @__PURE__ */ new Set()) {
10469
+ function json2(value, ancestors = /* @__PURE__ */ new Set()) {
10292
10470
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
10293
10471
  if (typeof value === "number") return Number.isFinite(value);
10294
10472
  if (typeof value !== "object" || ancestors.has(value)) return false;
@@ -10296,12 +10474,12 @@ function json(value, ancestors = /* @__PURE__ */ new Set()) {
10296
10474
  if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
10297
10475
  return false;
10298
10476
  ancestors.add(value);
10299
- const valid = Object.values(value).every((v) => json(v, ancestors));
10477
+ const valid = Object.values(value).every((v) => json2(v, ancestors));
10300
10478
  ancestors.delete(value);
10301
10479
  return valid;
10302
10480
  }
10303
10481
  function validRecord(value) {
10304
- if (!object(value) || typeof value.kind !== "string" || !kinds.has(value.kind) || !id(value.id) || !integer(value.sortKey) || !integer(value.createdAt, 1) || !integer(value.updatedAt, 1) || typeof value.isDeleted !== "boolean" || !object(value.data) || !json(value.data) || Object.keys(value).some(
10482
+ if (!object(value) || typeof value.kind !== "string" || !kinds.has(value.kind) || !id(value.id) || !integer(value.sortKey) || !integer(value.createdAt, 1) || !integer(value.updatedAt, 1) || typeof value.isDeleted !== "boolean" || !object(value.data) || !json2(value.data) || Object.keys(value).some(
10305
10483
  (key) => ![...metadata, "data"].includes(key)
10306
10484
  ))
10307
10485
  return false;
@@ -10330,14 +10508,14 @@ function vectorFields(write) {
10330
10508
  ...write.embeddingModel !== void 0 ? { embedding_model: write.embeddingModel } : {}
10331
10509
  };
10332
10510
  }
10333
- function text2(value) {
10511
+ function text3(value) {
10334
10512
  return typeof value === "string";
10335
10513
  }
10336
10514
  function timestamp(value) {
10337
10515
  return typeof value === "string" && Number.isFinite(Date.parse(value));
10338
10516
  }
10339
10517
  function presigned(value) {
10340
- if (!object(value) || !text2(value.url) || !/^https:\/\//.test(value.url) || !text2(value.method) || !object(value.headers) || !Object.values(value.headers).every(text2) || !timestamp(value.expires_at))
10518
+ if (!object(value) || !text3(value.url) || !/^https:\/\//.test(value.url) || !text3(value.method) || !object(value.headers) || !Object.values(value.headers).every(text3) || !timestamp(value.expires_at))
10341
10519
  invalid();
10342
10520
  return {
10343
10521
  url: value.url,
@@ -10347,7 +10525,7 @@ function presigned(value) {
10347
10525
  };
10348
10526
  }
10349
10527
  function attachment(value) {
10350
- if (!object(value) || !text2(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))
10528
+ if (!object(value) || !text3(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))
10351
10529
  invalid();
10352
10530
  return {
10353
10531
  id: value.attachment_id,
@@ -10360,7 +10538,7 @@ function attachment(value) {
10360
10538
  };
10361
10539
  }
10362
10540
  function ref(value) {
10363
- if (!object(value) || !text2(value.kind) || !kinds.has(value.kind) || !id(value.id)) invalid();
10541
+ if (!object(value) || !text3(value.kind) || !kinds.has(value.kind) || !id(value.id)) invalid();
10364
10542
  return { kind: value.kind, id: value.id };
10365
10543
  }
10366
10544
  function sameMetadata(a, b) {
@@ -10583,7 +10761,7 @@ async function createRemoteChatStore(options) {
10583
10761
  },
10584
10762
  async account(signal) {
10585
10763
  const value = await request("/account", {}, signal);
10586
- if (!object(value) || value.account_id !== accountId || !text2(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count))
10764
+ if (!object(value) || value.account_id !== accountId || !text3(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count))
10587
10765
  invalid();
10588
10766
  if (value.key_id && value.key_id !== keyId)
10589
10767
  throw new ChatStoreError("Canonical chat key does not match", 409, "key_mismatch");
@@ -10657,12 +10835,12 @@ async function createRemoteChatStore(options) {
10657
10835
  },
10658
10836
  async changes(cursor, options2) {
10659
10837
  const limit = options2?.limit ?? 100;
10660
- if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text2(cursor) || cursor.length > 2048))
10838
+ if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text3(cursor) || cursor.length > 2048))
10661
10839
  invalid();
10662
10840
  const params = new URLSearchParams({ account_id: String(accountId), limit: String(limit) });
10663
10841
  if (cursor) params.set("cursor", cursor);
10664
10842
  const value = await request(`/changes?${params}`, {}, options2?.signal);
10665
- if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !text2(value.next_cursor) || value.changes_cursor !== void 0 && !text2(value.changes_cursor))
10843
+ if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !text3(value.next_cursor) || value.changes_cursor !== void 0 && !text3(value.changes_cursor))
10666
10844
  invalid();
10667
10845
  const items = [];
10668
10846
  for (const item of value.items) items.push(await decode(item));
@@ -10853,141 +11031,6 @@ async function decryptConversationTitle(encryptedTitle, address) {
10853
11031
  }
10854
11032
  }
10855
11033
 
10856
- // src/lib/db/chat/models.ts
10857
- import { Model as Model2 } from "@nozbe/watermelondb";
10858
- import { date, field, json as json2, text as text3 } from "@nozbe/watermelondb/decorators";
10859
- var Message = class extends Model2 {
10860
- };
10861
- Message.table = "history";
10862
- Message.associations = {
10863
- conversations: { type: "belongs_to", key: "conversation_id" },
10864
- media: { type: "has_many", foreignKey: "message_id" }
10865
- };
10866
- __decorateClass([
10867
- field("message_id")
10868
- ], Message.prototype, "messageId", 2);
10869
- __decorateClass([
10870
- text3("conversation_id")
10871
- ], Message.prototype, "conversationId", 2);
10872
- __decorateClass([
10873
- text3("role")
10874
- ], Message.prototype, "role", 2);
10875
- __decorateClass([
10876
- text3("content")
10877
- ], Message.prototype, "content", 2);
10878
- __decorateClass([
10879
- text3("model")
10880
- ], Message.prototype, "model", 2);
10881
- __decorateClass([
10882
- text3("image_model")
10883
- ], Message.prototype, "imageModel", 2);
10884
- __decorateClass([
10885
- json2("files", (raw) => raw)
10886
- ], Message.prototype, "files", 2);
10887
- __decorateClass([
10888
- json2("file_ids", (raw) => raw)
10889
- ], Message.prototype, "fileIds", 2);
10890
- __decorateClass([
10891
- date("created_at")
10892
- ], Message.prototype, "createdAt", 2);
10893
- __decorateClass([
10894
- date("updated_at")
10895
- ], Message.prototype, "updatedAt", 2);
10896
- __decorateClass([
10897
- json2("vector", (raw) => raw)
10898
- ], Message.prototype, "vector", 2);
10899
- __decorateClass([
10900
- text3("embedding_model")
10901
- ], Message.prototype, "embeddingModel", 2);
10902
- __decorateClass([
10903
- json2("chunks", (raw) => raw)
10904
- ], Message.prototype, "chunks", 2);
10905
- __decorateClass([
10906
- json2("usage", (raw) => raw)
10907
- ], Message.prototype, "usage", 2);
10908
- __decorateClass([
10909
- json2("sources", (raw) => raw)
10910
- ], Message.prototype, "sources", 2);
10911
- __decorateClass([
10912
- field("response_duration")
10913
- ], Message.prototype, "responseDuration", 2);
10914
- __decorateClass([
10915
- field("was_stopped")
10916
- ], Message.prototype, "wasStopped", 2);
10917
- __decorateClass([
10918
- text3("error")
10919
- ], Message.prototype, "error", 2);
10920
- __decorateClass([
10921
- json2("thought_process", (raw) => raw)
10922
- ], Message.prototype, "thoughtProcess", 2);
10923
- __decorateClass([
10924
- text3("thinking")
10925
- ], Message.prototype, "thinking", 2);
10926
- __decorateClass([
10927
- text3("parent_message_id")
10928
- ], Message.prototype, "parentMessageId", 2);
10929
- __decorateClass([
10930
- text3("feedback")
10931
- ], Message.prototype, "feedback", 2);
10932
- __decorateClass([
10933
- json2("tool_call_events", (raw) => raw)
10934
- ], Message.prototype, "toolCallEvents", 2);
10935
- __decorateClass([
10936
- text3("origin")
10937
- ], Message.prototype, "origin", 2);
10938
- var Conversation = class extends Model2 {
10939
- };
10940
- Conversation.table = "conversations";
10941
- Conversation.associations = {
10942
- history: { type: "has_many", foreignKey: "conversation_id" },
10943
- projects: { type: "belongs_to", key: "project_id" }
10944
- };
10945
- __decorateClass([
10946
- text3("conversation_id")
10947
- ], Conversation.prototype, "conversationId", 2);
10948
- __decorateClass([
10949
- text3("title")
10950
- ], Conversation.prototype, "title", 2);
10951
- __decorateClass([
10952
- text3("project_id")
10953
- ], Conversation.prototype, "projectId", 2);
10954
- __decorateClass([
10955
- date("created_at")
10956
- ], Conversation.prototype, "createdAt", 2);
10957
- __decorateClass([
10958
- date("updated_at")
10959
- ], Conversation.prototype, "updatedAt", 2);
10960
- __decorateClass([
10961
- field("is_deleted")
10962
- ], Conversation.prototype, "isDeleted", 2);
10963
- __decorateClass([
10964
- date("pinned_at")
10965
- ], Conversation.prototype, "pinnedAt", 2);
10966
- var ConversationSummary = class extends Model2 {
10967
- };
10968
- ConversationSummary.table = "conversation_summaries";
10969
- ConversationSummary.associations = {
10970
- conversations: { type: "belongs_to", key: "conversation_id" }
10971
- };
10972
- __decorateClass([
10973
- text3("conversation_id")
10974
- ], ConversationSummary.prototype, "conversationId", 2);
10975
- __decorateClass([
10976
- text3("summary")
10977
- ], ConversationSummary.prototype, "summary", 2);
10978
- __decorateClass([
10979
- text3("summarized_up_to")
10980
- ], ConversationSummary.prototype, "summarizedUpTo", 2);
10981
- __decorateClass([
10982
- field("token_count")
10983
- ], ConversationSummary.prototype, "tokenCount", 2);
10984
- __decorateClass([
10985
- date("created_at")
10986
- ], ConversationSummary.prototype, "createdAt", 2);
10987
- __decorateClass([
10988
- date("updated_at")
10989
- ], ConversationSummary.prototype, "updatedAt", 2);
10990
-
10991
11034
  // src/lib/db/chat/schema.ts
10992
11035
  import { appSchema, tableSchema } from "@nozbe/watermelondb";
10993
11036
  import { addColumns, schemaMigrations } from "@nozbe/watermelondb/Schema/migrations";
@@ -27486,6 +27529,13 @@ var lastCompactionTime = /* @__PURE__ */ new Map();
27486
27529
  var COMPACTION_COOLDOWN_MS = 6e4;
27487
27530
  var MAX_SUMMARY_TOKEN_RATIO = 0.8;
27488
27531
  async function maybeSummarizeHistory(options) {
27532
+ const { database, conversationId } = options;
27533
+ const revision2 = getConversationRevision(database, conversationId);
27534
+ const result = await summarizeHistoryAtRevision(options, revision2);
27535
+ assertConversationRevision(database, conversationId, revision2);
27536
+ return result;
27537
+ }
27538
+ async function summarizeHistoryAtRevision(options, revision2) {
27489
27539
  const { database, conversationId, messages, summarizeHistory, summaryMinWindowMessages, token } = options;
27490
27540
  if (!summarizeHistory) {
27491
27541
  return { messagesToConvert: messages, summarySystemMessage: null };
@@ -27526,7 +27576,7 @@ async function maybeSummarizeHistory(options) {
27526
27576
  clearTimeout(staleGuardTimerId);
27527
27577
  }
27528
27578
  }
27529
- const promise = doSummarizeHistory(options);
27579
+ const promise = doSummarizeHistory(options, revision2);
27530
27580
  summarizationLocks.set(conversationId, promise);
27531
27581
  try {
27532
27582
  return await promise;
@@ -27540,7 +27590,7 @@ Summary to condense:
27540
27590
  {summary}
27541
27591
 
27542
27592
  Condensed summary:`;
27543
- async function doSummarizeHistory(options) {
27593
+ async function doSummarizeHistory(options, revision2) {
27544
27594
  const {
27545
27595
  database,
27546
27596
  conversationId,
@@ -27555,7 +27605,20 @@ async function doSummarizeHistory(options) {
27555
27605
  } = options;
27556
27606
  try {
27557
27607
  const summaryCtx = createSummaryContext(database);
27608
+ const persistSummary = (summary, summarizedUpTo, tokenCount) => database.write(async (writer) => {
27609
+ assertConversationRevision(database, conversationId, revision2);
27610
+ await writer.callWriter(
27611
+ () => upsertConversationSummaryOp(
27612
+ summaryCtx,
27613
+ conversationId,
27614
+ summary,
27615
+ summarizedUpTo,
27616
+ tokenCount
27617
+ )
27618
+ );
27619
+ });
27558
27620
  let cachedSummary = await getConversationSummaryOp(summaryCtx, conversationId);
27621
+ assertConversationRevision(database, conversationId, revision2);
27559
27622
  const lastCompacted = lastCompactionTime.get(conversationId) ?? 0;
27560
27623
  const compactionCooledDown = Date.now() - lastCompacted > COMPACTION_COOLDOWN_MS;
27561
27624
  if (cachedSummary && cachedSummary.tokenCount > summaryTokenThreshold * MAX_SUMMARY_TOKEN_RATIO && compactionCooledDown) {
@@ -27571,13 +27634,7 @@ async function doSummarizeHistory(options) {
27571
27634
  );
27572
27635
  const compactedSummary = redactor ? redactor.deAnonymize(rawCompacted) : rawCompacted;
27573
27636
  const compactedTokens = estimateTokens(compactedSummary);
27574
- await upsertConversationSummaryOp(
27575
- summaryCtx,
27576
- conversationId,
27577
- compactedSummary,
27578
- cachedSummary.summarizedUpTo,
27579
- compactedTokens
27580
- );
27637
+ await persistSummary(compactedSummary, cachedSummary.summarizedUpTo, compactedTokens);
27581
27638
  cachedSummary = {
27582
27639
  ...cachedSummary,
27583
27640
  summary: compactedSummary,
@@ -27585,6 +27642,7 @@ async function doSummarizeHistory(options) {
27585
27642
  };
27586
27643
  lastCompactionTime.set(conversationId, Date.now());
27587
27644
  } catch {
27645
+ assertConversationRevision(database, conversationId, revision2);
27588
27646
  lastCompactionTime.set(conversationId, Date.now());
27589
27647
  getLogger().warn(
27590
27648
  "[summarize] Summary compaction failed, proceeding with oversized summary"
@@ -27616,10 +27674,9 @@ async function doSummarizeHistory(options) {
27616
27674
  redactor,
27617
27675
  onPiiRedacted
27618
27676
  });
27677
+ assertConversationRevision(database, conversationId, revision2);
27619
27678
  if (summarizeResult.didSummarize && summarizeResult.summary && summarizeResult.summarizedUpTo) {
27620
- await upsertConversationSummaryOp(
27621
- summaryCtx,
27622
- conversationId,
27679
+ await persistSummary(
27623
27680
  summarizeResult.summary,
27624
27681
  summarizeResult.summarizedUpTo,
27625
27682
  summarizeResult.summaryTokenCount
@@ -27638,6 +27695,7 @@ async function doSummarizeHistory(options) {
27638
27695
  summarySystemMessage: summarizeResult.summary ? summaryToSystemMessage(summarizeResult.summary) : null
27639
27696
  };
27640
27697
  } catch (err) {
27698
+ assertConversationRevision(database, conversationId, revision2);
27641
27699
  getLogger().warn("[summarize] Summarization failed, falling back to verbatim:", err);
27642
27700
  return { messagesToConvert: messages, summarySystemMessage: null };
27643
27701
  }