@anuma/sdk 10.8.0 → 10.9.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.
@@ -9923,118 +9923,19 @@ var xhrTransport = (options) => {
9923
9923
  return { stream: createStream() };
9924
9924
  };
9925
9925
 
9926
- // src/lib/db/chat/summaryOperations.ts
9927
- import { Q as Q3 } from "@nozbe/watermelondb";
9928
- function createSummaryContext(database, encryption = {}) {
9929
- return {
9930
- ...encryption,
9931
- database,
9932
- summariesCollection: database.get("conversation_summaries")
9933
- };
9934
- }
9935
- function modelToStored(record2, summary) {
9936
- return {
9937
- uniqueId: record2.id,
9938
- conversationId: record2.conversationId,
9939
- summary,
9940
- summarizedUpTo: record2.summarizedUpTo,
9941
- tokenCount: record2.tokenCount,
9942
- createdAt: record2.createdAt,
9943
- updatedAt: record2.updatedAt
9944
- };
9945
- }
9946
- async function getConversationSummaryOp(ctx, conversationId) {
9947
- const results = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
9948
- if (results.length === 0) return null;
9949
- const record2 = results[0];
9950
- const stored2 = modelToStored(record2, record2.summary);
9951
- if (ctx.walletAddress && isEncrypted(stored2.summary)) {
9952
- if (ctx.signMessage) {
9953
- try {
9954
- await requestEncryptionKey(ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
9955
- } catch (error) {
9956
- getLogger().warn("Failed to request the encryption key for the summary:", error);
9957
- }
9958
- }
9959
- stored2.summary = await decryptField(stored2.summary, ctx.walletAddress);
9960
- } else if (ctx.walletAddress && ctx.signMessage && stored2.summary) {
9961
- try {
9962
- const encryptedSummary = await encryptField(
9963
- stored2.summary,
9964
- ctx.walletAddress,
9965
- ctx.signMessage,
9966
- ctx.embeddedWalletSigner
9967
- );
9968
- await ctx.database.write(async () => {
9969
- const current = await ctx.summariesCollection.query(Q3.where("id", record2.id)).fetch();
9970
- if (current[0]?.summary === stored2.summary) {
9971
- await current[0].update((rec) => {
9972
- rec.summary = encryptedSummary;
9973
- });
9974
- }
9975
- });
9976
- } catch (error) {
9977
- getLogger().warn("Failed to encrypt the legacy summary:", error);
9978
- }
9926
+ // src/lib/chatStore/types.ts
9927
+ var ChatStoreError = class extends Error {
9928
+ constructor(message, status, code, retryAfterMs) {
9929
+ super(message);
9930
+ this.status = status;
9931
+ this.code = code;
9932
+ this.retryAfterMs = retryAfterMs;
9933
+ this.name = "ChatStoreError";
9979
9934
  }
9980
- return stored2;
9981
- }
9982
- async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
9983
- const revision2 = getConversationRevision(ctx.database, conversationId);
9984
- let record2;
9985
- const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
9986
- await ctx.database.write(async () => {
9987
- assertConversationRevision(ctx.database, conversationId, revision2);
9988
- const existing = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
9989
- if (existing.length > 0) {
9990
- record2 = await existing[0].update((rec) => {
9991
- rec.summary = encryptedSummary;
9992
- rec.summarizedUpTo = summarizedUpTo;
9993
- rec.tokenCount = tokenCount;
9994
- });
9995
- } else {
9996
- record2 = await ctx.summariesCollection.create((rec) => {
9997
- rec.conversationId = conversationId;
9998
- rec.summary = encryptedSummary;
9999
- rec.summarizedUpTo = summarizedUpTo;
10000
- rec.tokenCount = tokenCount;
10001
- });
10002
- }
10003
- });
10004
- return modelToStored(record2, summary);
10005
- }
10006
- async function deleteConversationSummaryOp(ctx, conversationId) {
10007
- await ctx.database.write(async () => {
10008
- const existing = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
10009
- for (const record2 of existing) {
10010
- await record2.destroyPermanently();
10011
- }
10012
- });
10013
- }
10014
-
10015
- // src/lib/db/conversationMemory/models.ts
10016
- import { Model as Model3 } from "@nozbe/watermelondb";
10017
- import { date as date2, field as field2, readonly, text as text3 } from "@nozbe/watermelondb/decorators";
10018
- var ConversationMemory = class extends Model3 {
10019
9935
  };
10020
- ConversationMemory.table = "conversation_memory";
10021
- ConversationMemory.associations = {};
10022
- __decorateClass([
10023
- text3("conversation_id")
10024
- ], ConversationMemory.prototype, "conversationId", 2);
10025
- __decorateClass([
10026
- text3("memory_id")
10027
- ], ConversationMemory.prototype, "memoryId", 2);
10028
- __decorateClass([
10029
- field2("score")
10030
- ], ConversationMemory.prototype, "score", 2);
10031
- __decorateClass([
10032
- readonly,
10033
- date2("created_at")
10034
- ], ConversationMemory.prototype, "createdAt", 2);
10035
9936
 
10036
9937
  // src/lib/db/conversationMemory/operations.ts
10037
- import { Q as Q4 } from "@nozbe/watermelondb";
9938
+ import { Q as Q3 } from "@nozbe/watermelondb";
10038
9939
  var MAX_PER_CONVERSATION = 200;
10039
9940
  function conversationMemoryToStored(row) {
10040
9941
  return {
@@ -10049,7 +9950,7 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
10049
9950
  if (!conversationId || items.length === 0) return;
10050
9951
  const now = Date.now();
10051
9952
  await ctx.database.write(async () => {
10052
- const existing = await ctx.conversationMemoryCollection.query(Q4.where("conversation_id", conversationId), Q4.sortBy("created_at", Q4.asc)).fetch();
9953
+ const existing = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId), Q3.sortBy("created_at", Q3.asc)).fetch();
10053
9954
  const seen = new Set(existing.map((r) => r.memoryId));
10054
9955
  const batchSeen = /* @__PURE__ */ new Set();
10055
9956
  const deduped = [];
@@ -10086,7 +9987,7 @@ async function recordConversationMemoriesOp(ctx, conversationId, items, now = Da
10086
9987
  if (!conversationId || turn.size === 0) return;
10087
9988
  const kept = new Map([...turn].slice(-MAX_PER_CONVERSATION));
10088
9989
  await ctx.database.write(async () => {
10089
- const existing = await ctx.conversationMemoryCollection.query(Q4.where("conversation_id", conversationId), Q4.sortBy("created_at", Q4.asc)).fetch();
9990
+ const existing = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId), Q3.sortBy("created_at", Q3.asc)).fetch();
10090
9991
  const earlier = existing.filter((r) => !turn.has(r.memoryId));
10091
9992
  const linked = new Set(existing.map((r) => r.memoryId));
10092
9993
  await ctx.database.batch(
@@ -10111,13 +10012,13 @@ async function recordConversationMemoriesOp(ctx, conversationId, items, now = Da
10111
10012
  }
10112
10013
  async function getConversationMemoriesOp(ctx, conversationId) {
10113
10014
  if (!conversationId) return [];
10114
- const rows = await ctx.conversationMemoryCollection.query(Q4.where("conversation_id", conversationId), Q4.sortBy("created_at", Q4.asc)).fetch();
10015
+ const rows = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId), Q3.sortBy("created_at", Q3.asc)).fetch();
10115
10016
  return rows.map(conversationMemoryToStored);
10116
10017
  }
10117
10018
  async function clearConversationMemoriesOp(ctx, conversationId) {
10118
10019
  if (!conversationId) return;
10119
10020
  await ctx.database.write(async () => {
10120
- const rows = await ctx.conversationMemoryCollection.query(Q4.where("conversation_id", conversationId)).fetch();
10021
+ const rows = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId)).fetch();
10121
10022
  if (rows.length === 0) return;
10122
10023
  await ctx.database.batch(...rows.map((r) => r.prepareDestroyPermanently()));
10123
10024
  });
@@ -10132,15 +10033,37 @@ var maxChunks = 16;
10132
10033
  var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
10133
10034
  var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
10134
10035
  var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
10036
+ var maxBubbles = 3;
10037
+ var maxTurnIdBytes = 128;
10038
+ var maxBubbleBytes = 16384;
10039
+ var anumaOrigins = /* @__PURE__ */ new Set(["intro", "reply"]);
10135
10040
  function plain(value) {
10136
10041
  return JSON.parse(JSON.stringify(value ?? {}));
10137
10042
  }
10138
- function text4(value) {
10043
+ function text3(value) {
10139
10044
  return typeof value === "string" ? value : void 0;
10140
10045
  }
10141
10046
  function number(value) {
10142
10047
  return typeof value === "number" ? value : void 0;
10143
10048
  }
10049
+ function readAnumaTurn(value) {
10050
+ if (!isObject(value)) return void 0;
10051
+ const { turnId, bubbles, origin } = value;
10052
+ if (typeof turnId !== "string" || turnId.length === 0 || new TextEncoder().encode(turnId).length > maxTurnIdBytes)
10053
+ return void 0;
10054
+ if (bubbles !== void 0 && (!Array.isArray(bubbles) || bubbles.length < 1 || bubbles.length > maxBubbles || !bubbles.every((b) => typeof b === "string") || bubbles.reduce((sum, b) => sum + new TextEncoder().encode(b).length, 0) > maxBubbleBytes))
10055
+ return void 0;
10056
+ if (origin !== void 0 && (typeof origin !== "string" || !anumaOrigins.has(origin)))
10057
+ return void 0;
10058
+ return {
10059
+ turnId,
10060
+ ...bubbles !== void 0 ? { bubbles: [...bubbles] } : {},
10061
+ ...origin !== void 0 ? { origin } : {}
10062
+ };
10063
+ }
10064
+ function isObject(value) {
10065
+ return value !== null && typeof value === "object" && !Array.isArray(value);
10066
+ }
10144
10067
  function conversationSortKey(data, createdAt) {
10145
10068
  const pinnedAt = number(data.pinnedAt);
10146
10069
  if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
@@ -10161,12 +10084,12 @@ function conversationContext(data) {
10161
10084
  }
10162
10085
  function toConversation(record2) {
10163
10086
  const pinnedAt = number(record2.data.pinnedAt);
10164
- const projectId = text4(record2.data.projectId);
10087
+ const projectId = text3(record2.data.projectId);
10165
10088
  const context = conversationContext(record2.data);
10166
10089
  return {
10167
10090
  uniqueId: record2.id,
10168
10091
  conversationId: record2.id,
10169
- title: text4(record2.data.title) ?? "",
10092
+ title: text3(record2.data.title) ?? "",
10170
10093
  ...projectId ? { projectId } : {},
10171
10094
  createdAt: new Date(record2.createdAt),
10172
10095
  updatedAt: new Date(record2.updatedAt),
@@ -10175,18 +10098,28 @@ function toConversation(record2) {
10175
10098
  ...context ? { context } : {}
10176
10099
  };
10177
10100
  }
10101
+ function anumaTurnData(value) {
10102
+ if (value === void 0) return void 0;
10103
+ const turn = readAnumaTurn(value);
10104
+ if (!turn) throw new ChatStoreError("Invalid Anuma turn", 0, "invalid_record");
10105
+ return turn;
10106
+ }
10178
10107
  function messageData(options) {
10179
- return plain(
10180
- Object.fromEntries(
10108
+ const anuma = anumaTurnData(options.anuma);
10109
+ return plain({
10110
+ ...Object.fromEntries(
10181
10111
  Object.entries(options).filter(
10182
- ([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
10112
+ ([key3, value]) => key3 !== "anuma" && !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
10183
10113
  )
10184
- )
10185
- );
10114
+ ),
10115
+ ...anuma ? { anuma } : {}
10116
+ });
10186
10117
  }
10187
10118
  function toMessage(record2) {
10188
- const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
10119
+ const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } = record2.data;
10120
+ const anuma = readAnumaTurn(rawAnuma);
10189
10121
  return {
10122
+ ...anuma ? { anuma } : {},
10190
10123
  ...fields,
10191
10124
  uniqueId: record2.id,
10192
10125
  messageId: record2.sortKey,
@@ -10200,20 +10133,20 @@ function chunkOffsets(record2) {
10200
10133
  return Array.isArray(offsets) ? offsets : void 0;
10201
10134
  }
10202
10135
  function toSkeletons(records) {
10203
- const roleById = new Map(records.map((r) => [r.id, text4(r.data.role)]));
10136
+ const roleById = new Map(records.map((r) => [r.id, text3(r.data.role)]));
10204
10137
  return records.map((r) => {
10205
- const parentMessageId = text4(r.data.parentMessageId);
10206
- const model = text4(r.data.model);
10138
+ const parentMessageId = text3(r.data.parentMessageId);
10139
+ const model = text3(r.data.model);
10207
10140
  const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
10208
10141
  return {
10209
10142
  uniqueId: r.id,
10210
10143
  messageId: r.sortKey,
10211
10144
  conversationId: r.conversationId,
10212
- role: text4(r.data.role) ?? "",
10145
+ role: text3(r.data.role) ?? "",
10213
10146
  createdAt: new Date(r.createdAt),
10214
10147
  ...parentMessageId ? { parentMessageId } : {},
10215
10148
  ...model ? { model } : {},
10216
- ...artifact ? { content: text4(r.data.content) ?? "" } : {}
10149
+ ...artifact ? { content: text3(r.data.content) ?? "" } : {}
10217
10150
  };
10218
10151
  });
10219
10152
  }
@@ -10221,8 +10154,8 @@ function toSummary(record2) {
10221
10154
  return {
10222
10155
  uniqueId: record2.id,
10223
10156
  conversationId: record2.id,
10224
- summary: text4(record2.data.summary) ?? "",
10225
- summarizedUpTo: text4(record2.data.summarizedUpTo) ?? "",
10157
+ summary: text3(record2.data.summary) ?? "",
10158
+ summarizedUpTo: text3(record2.data.summarizedUpTo) ?? "",
10226
10159
  tokenCount: number(record2.data.tokenCount) ?? 0,
10227
10160
  createdAt: new Date(record2.createdAt),
10228
10161
  updatedAt: new Date(record2.updatedAt)
@@ -10273,7 +10206,7 @@ function fitRecord(record2) {
10273
10206
  delete data[field10];
10274
10207
  truncated.push(field10);
10275
10208
  }
10276
- const content = text4(data.content) ?? "";
10209
+ const content = text3(data.content) ?? "";
10277
10210
  const over = bytes({ ...record2, data }) - recordBudgetBytes;
10278
10211
  if (over > 0) {
10279
10212
  const encoded = new TextEncoder().encode(content);
@@ -10317,6 +10250,215 @@ function fitChunks(chunks3) {
10317
10250
  return out;
10318
10251
  }
10319
10252
 
10253
+ // src/lib/chatStore/anuma.ts
10254
+ var ANUMA_CONVERSATION_ID = "anuma-1on1";
10255
+ var maxAttempts = 3;
10256
+ function anumaTurnContent(bubbles) {
10257
+ return bubbles.join("\n\n");
10258
+ }
10259
+ function anumaLastReadSortKey(conversation) {
10260
+ const record2 = conversation && "record" in conversation ? conversation.record : conversation;
10261
+ const state = record2?.data.anuma;
10262
+ if (!isObject(state)) return 0;
10263
+ const sortKey = state.lastReadSortKey;
10264
+ return Number.isSafeInteger(sortKey) && sortKey > 0 ? sortKey : 0;
10265
+ }
10266
+ function conflict(error) {
10267
+ return error instanceof ChatStoreError && error.code === "version_conflict";
10268
+ }
10269
+ function live(snapshot) {
10270
+ if (snapshot?.record.isDeleted)
10271
+ throw new ChatStoreError("Anuma conversation was deleted", 409, "conversation_deleted");
10272
+ return snapshot;
10273
+ }
10274
+ async function ensureAnumaConversation(store, options = {}) {
10275
+ const existing = live(await store.get("conversation", ANUMA_CONVERSATION_ID, options.signal));
10276
+ if (existing) return existing;
10277
+ const at = (options.now ?? Date.now)();
10278
+ const data = plain({ title: "Anuma", lastActivityAt: at, anuma: { lastReadSortKey: 0 } });
10279
+ try {
10280
+ const [created] = await store.putMany(
10281
+ [
10282
+ {
10283
+ expectedVersion: 0,
10284
+ record: {
10285
+ kind: "conversation",
10286
+ id: ANUMA_CONVERSATION_ID,
10287
+ conversationId: "",
10288
+ sortKey: conversationSortKey(data, at),
10289
+ createdAt: at,
10290
+ updatedAt: at,
10291
+ isDeleted: false,
10292
+ data
10293
+ }
10294
+ }
10295
+ ],
10296
+ options.signal
10297
+ );
10298
+ return created;
10299
+ } catch (error) {
10300
+ if (!conflict(error)) throw error;
10301
+ const winner = live(await store.get("conversation", ANUMA_CONVERSATION_ID, options.signal));
10302
+ if (!winner) throw error;
10303
+ return winner;
10304
+ }
10305
+ }
10306
+ async function markAnumaRead(store, sortKey, options = {}) {
10307
+ if (!Number.isSafeInteger(sortKey) || sortKey < 0)
10308
+ throw new ChatStoreError("Invalid Anuma read marker", 0, "invalid_record");
10309
+ const now = options.now ?? Date.now;
10310
+ for (let attempt = 1; ; attempt++) {
10311
+ const current = await ensureAnumaConversation(store, options);
10312
+ const read = anumaLastReadSortKey(current);
10313
+ if (sortKey <= read) return current;
10314
+ const record2 = current.record;
10315
+ const state = isObject(record2.data.anuma) ? record2.data.anuma : {};
10316
+ const data = plain({ ...record2.data, anuma: { ...state, lastReadSortKey: sortKey } });
10317
+ try {
10318
+ const [written] = await store.putMany(
10319
+ [
10320
+ {
10321
+ expectedVersion: current.version,
10322
+ record: {
10323
+ ...record2,
10324
+ data,
10325
+ sortKey: conversationSortKey(data, record2.createdAt),
10326
+ updatedAt: Math.max(record2.updatedAt, now())
10327
+ }
10328
+ }
10329
+ ],
10330
+ options.signal
10331
+ );
10332
+ return written;
10333
+ } catch (error) {
10334
+ if (!conflict(error) || attempt >= maxAttempts) throw error;
10335
+ }
10336
+ }
10337
+ }
10338
+ function countUnreadAnumaTurns(messages, lastReadSortKey) {
10339
+ const answered = Math.max(
10340
+ 0,
10341
+ ...messages.filter((m) => m.role === "user").map((m) => m.messageId)
10342
+ );
10343
+ const floor = Math.max(lastReadSortKey, answered);
10344
+ const turns = /* @__PURE__ */ new Set();
10345
+ for (const m of messages) {
10346
+ if (m.role !== "assistant" || m.messageId <= floor) continue;
10347
+ turns.add(m.anuma?.turnId ? `turn:${m.anuma.turnId}` : `message:${m.uniqueId}`);
10348
+ }
10349
+ return turns.size;
10350
+ }
10351
+
10352
+ // src/lib/db/chat/summaryOperations.ts
10353
+ import { Q as Q4 } from "@nozbe/watermelondb";
10354
+ function createSummaryContext(database, encryption = {}) {
10355
+ return {
10356
+ ...encryption,
10357
+ database,
10358
+ summariesCollection: database.get("conversation_summaries")
10359
+ };
10360
+ }
10361
+ function modelToStored(record2, summary) {
10362
+ return {
10363
+ uniqueId: record2.id,
10364
+ conversationId: record2.conversationId,
10365
+ summary,
10366
+ summarizedUpTo: record2.summarizedUpTo,
10367
+ tokenCount: record2.tokenCount,
10368
+ createdAt: record2.createdAt,
10369
+ updatedAt: record2.updatedAt
10370
+ };
10371
+ }
10372
+ async function getConversationSummaryOp(ctx, conversationId) {
10373
+ const results = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
10374
+ if (results.length === 0) return null;
10375
+ const record2 = results[0];
10376
+ const stored2 = modelToStored(record2, record2.summary);
10377
+ if (ctx.walletAddress && isEncrypted(stored2.summary)) {
10378
+ if (ctx.signMessage) {
10379
+ try {
10380
+ await requestEncryptionKey(ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
10381
+ } catch (error) {
10382
+ getLogger().warn("Failed to request the encryption key for the summary:", error);
10383
+ }
10384
+ }
10385
+ stored2.summary = await decryptField(stored2.summary, ctx.walletAddress);
10386
+ } else if (ctx.walletAddress && ctx.signMessage && stored2.summary) {
10387
+ try {
10388
+ const encryptedSummary = await encryptField(
10389
+ stored2.summary,
10390
+ ctx.walletAddress,
10391
+ ctx.signMessage,
10392
+ ctx.embeddedWalletSigner
10393
+ );
10394
+ await ctx.database.write(async () => {
10395
+ const current = await ctx.summariesCollection.query(Q4.where("id", record2.id)).fetch();
10396
+ if (current[0]?.summary === stored2.summary) {
10397
+ await current[0].update((rec) => {
10398
+ rec.summary = encryptedSummary;
10399
+ });
10400
+ }
10401
+ });
10402
+ } catch (error) {
10403
+ getLogger().warn("Failed to encrypt the legacy summary:", error);
10404
+ }
10405
+ }
10406
+ return stored2;
10407
+ }
10408
+ async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
10409
+ const revision2 = getConversationRevision(ctx.database, conversationId);
10410
+ let record2;
10411
+ const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
10412
+ await ctx.database.write(async () => {
10413
+ assertConversationRevision(ctx.database, conversationId, revision2);
10414
+ const existing = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
10415
+ if (existing.length > 0) {
10416
+ record2 = await existing[0].update((rec) => {
10417
+ rec.summary = encryptedSummary;
10418
+ rec.summarizedUpTo = summarizedUpTo;
10419
+ rec.tokenCount = tokenCount;
10420
+ });
10421
+ } else {
10422
+ record2 = await ctx.summariesCollection.create((rec) => {
10423
+ rec.conversationId = conversationId;
10424
+ rec.summary = encryptedSummary;
10425
+ rec.summarizedUpTo = summarizedUpTo;
10426
+ rec.tokenCount = tokenCount;
10427
+ });
10428
+ }
10429
+ });
10430
+ return modelToStored(record2, summary);
10431
+ }
10432
+ async function deleteConversationSummaryOp(ctx, conversationId) {
10433
+ await ctx.database.write(async () => {
10434
+ const existing = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
10435
+ for (const record2 of existing) {
10436
+ await record2.destroyPermanently();
10437
+ }
10438
+ });
10439
+ }
10440
+
10441
+ // src/lib/db/conversationMemory/models.ts
10442
+ import { Model as Model3 } from "@nozbe/watermelondb";
10443
+ import { date as date2, field as field2, readonly, text as text4 } from "@nozbe/watermelondb/decorators";
10444
+ var ConversationMemory = class extends Model3 {
10445
+ };
10446
+ ConversationMemory.table = "conversation_memory";
10447
+ ConversationMemory.associations = {};
10448
+ __decorateClass([
10449
+ text4("conversation_id")
10450
+ ], ConversationMemory.prototype, "conversationId", 2);
10451
+ __decorateClass([
10452
+ text4("memory_id")
10453
+ ], ConversationMemory.prototype, "memoryId", 2);
10454
+ __decorateClass([
10455
+ field2("score")
10456
+ ], ConversationMemory.prototype, "score", 2);
10457
+ __decorateClass([
10458
+ readonly,
10459
+ date2("created_at")
10460
+ ], ConversationMemory.prototype, "createdAt", 2);
10461
+
10320
10462
  // src/lib/chatStore/chatImports.ts
10321
10463
  var importBatch = 100;
10322
10464
  var importChunks = 200;
@@ -10897,17 +11039,17 @@ async function createRemoteMemoryPersistence(options) {
10897
11039
  expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
10898
11040
  if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
10899
11041
  throw new Error("expectedVersion must be a nonnegative integer");
10900
- const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
11042
+ const conflict2 = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
10901
11043
  let existing;
10902
11044
  if (expectedVersion !== 0 && !snapshot) {
10903
11045
  try {
10904
11046
  existing = memoryRecord(await request(path, {}, signal));
10905
11047
  } catch (error) {
10906
- if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
11048
+ if (error instanceof RemoteMemoryError && error.status === 404) throw conflict2();
10907
11049
  throw error;
10908
11050
  }
10909
11051
  }
10910
- if (existing && existing.version !== expectedVersion) throw conflict();
11052
+ if (existing && existing.version !== expectedVersion) throw conflict2();
10911
11053
  const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
10912
11054
  const reusableContent = snapshot?.encryptedContent ?? existing?.memory.content;
10913
11055
  const content = reusableContent && (snapshot?.content ?? decoded?.memory.content) === memory.content ? reusableContent : await encryptField2(memory.content);
@@ -11132,17 +11274,6 @@ async function createRemoteMemoryPersistence(options) {
11132
11274
  };
11133
11275
  }
11134
11276
 
11135
- // src/lib/chatStore/types.ts
11136
- var ChatStoreError = class extends Error {
11137
- constructor(message, status, code, retryAfterMs) {
11138
- super(message);
11139
- this.status = status;
11140
- this.code = code;
11141
- this.retryAfterMs = retryAfterMs;
11142
- this.name = "ChatStoreError";
11143
- }
11144
- };
11145
-
11146
11277
  // src/lib/chatStore/remote.ts
11147
11278
  var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links", "setting"]);
11148
11279
  var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
@@ -11867,10 +11998,10 @@ async function deletedSinceUpload(store, journal, local, signal) {
11867
11998
  const present = /* @__PURE__ */ new Set([...local.records.map((r) => key(r.record)), ...local.skipped.keys()]);
11868
11999
  const gone = [...journal.keys].filter((k) => !present.has(k));
11869
12000
  if (gone.length === 0) return [];
11870
- const live = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
11871
- const tombstoning = new Set(live.map((s) => key(s.record)));
12001
+ const live2 = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
12002
+ const tombstoning = new Set(live2.map((s) => key(s.record)));
11872
12003
  await journal.drop(gone.filter((k) => !tombstoning.has(k)));
11873
- return live.map(({ record: record2, version }) => {
12004
+ return live2.map(({ record: record2, version }) => {
11874
12005
  const empty = emptied[record2.kind];
11875
12006
  return {
11876
12007
  record: {
@@ -12530,12 +12661,13 @@ var resumableFields = [
12530
12661
  "error",
12531
12662
  "thoughtProcess",
12532
12663
  "thinking",
12533
- "toolCallEvents"
12664
+ "toolCallEvents",
12665
+ "anuma"
12534
12666
  ];
12535
12667
  function resumedFields(options) {
12536
12668
  return plain(
12537
12669
  Object.fromEntries(
12538
- resumableFields.filter((f) => options[f] !== void 0).map((f) => [f, options[f]])
12670
+ resumableFields.filter((f) => options[f] !== void 0).map((f) => [f, f === "anuma" ? anumaTurnData(options.anuma) : options[f]])
12539
12671
  )
12540
12672
  );
12541
12673
  }
@@ -13189,7 +13321,7 @@ function createVaultChatBackend(options) {
13189
13321
  },
13190
13322
  async getConversations(query) {
13191
13323
  await available2();
13192
- return all("conversation").map(toConversation).filter(
13324
+ return all("conversation").filter((record2) => record2.id !== ANUMA_CONVERSATION_ID).map(toConversation).filter(
13193
13325
  (c) => query?.projectId === void 0 || (query.projectId === null ? !c.projectId : c.projectId === query.projectId)
13194
13326
  ).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
13195
13327
  },
@@ -13232,6 +13364,7 @@ function createVaultChatBackend(options) {
13232
13364
  return !!record2 && !record2.isDeleted;
13233
13365
  },
13234
13366
  async deleteConversation(conversationId) {
13367
+ if (conversationId === ANUMA_CONVERSATION_ID) return false;
13235
13368
  const record2 = await conversation(conversationId);
13236
13369
  if (!record2 || record2.isDeleted) return false;
13237
13370
  for (const [k, patch] of pending)
@@ -16238,7 +16371,7 @@ async function countActiveVaultMemoriesOp(ctx) {
16238
16371
  return ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx)).fetchCount();
16239
16372
  }
16240
16373
  async function getVaultMemoryCountsOp(ctx) {
16241
- const [live, archived, quarantined] = await Promise.all([
16374
+ const [live2, archived, quarantined] = await Promise.all([
16242
16375
  countActiveVaultMemoriesOp(ctx),
16243
16376
  ctx.vaultMemoryCollection.query(
16244
16377
  ...baseVaultConditions(ctx, { includeArchived: true }),
@@ -16249,7 +16382,7 @@ async function getVaultMemoryCountsOp(ctx) {
16249
16382
  Q6.where("trust_tier", "quarantined")
16250
16383
  ).fetchCount()
16251
16384
  ]);
16252
- return { live, archived, quarantined };
16385
+ return { live: live2, archived, quarantined };
16253
16386
  }
16254
16387
  async function getActiveVaultMemoryIdsOp(ctx, ids) {
16255
16388
  if (ids.length === 0) return /* @__PURE__ */ new Set();
@@ -17534,12 +17667,12 @@ var WalletPoller = class {
17534
17667
  * @param maxAttempts - Maximum polling attempts before giving up (default: 60)
17535
17668
  * @returns Stop function to cancel polling
17536
17669
  */
17537
- startPolling(checkWallet, onWalletReady, intervalMs = DEFAULT_INTERVAL_MS, maxAttempts = DEFAULT_MAX_ATTEMPTS) {
17670
+ startPolling(checkWallet, onWalletReady, intervalMs = DEFAULT_INTERVAL_MS, maxAttempts2 = DEFAULT_MAX_ATTEMPTS) {
17538
17671
  this.stop();
17539
17672
  this.attempts = 0;
17540
17673
  const poll = async () => {
17541
17674
  this.attempts++;
17542
- if (this.attempts > maxAttempts) {
17675
+ if (this.attempts > maxAttempts2) {
17543
17676
  this.stop();
17544
17677
  return;
17545
17678
  }
@@ -24900,13 +25033,13 @@ function createRemoteMemoryStore(options) {
24900
25033
  });
24901
25034
  return run;
24902
25035
  };
24903
- const live = async (id2) => {
25036
+ const live2 = async (id2) => {
24904
25037
  const record2 = await persistence.get(id2);
24905
25038
  return record2 && !record2.memory.is_deleted ? record2 : null;
24906
25039
  };
24907
25040
  const mutateLocked = async (id2, change, edit, writeOptions) => {
24908
25041
  writeOptions?.signal?.throwIfAborted();
24909
- const record2 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live(id2);
25042
+ const record2 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live2(id2);
24910
25043
  if (!record2) return null;
24911
25044
  if (record2.memory.is_deleted) return null;
24912
25045
  if (writeOptions?.canWrite && !await writeOptions.canWrite())
@@ -25704,7 +25837,7 @@ function createRemoteMemoryStore(options) {
25704
25837
  }, clear);
25705
25838
  return snapshot.then((topics) => structuredClone(topics));
25706
25839
  },
25707
- get: async (id2) => asStored(await live(id2)),
25840
+ get: async (id2) => asStored(await live2(id2)),
25708
25841
  listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
25709
25842
  (record2) => stored(record2.memory)
25710
25843
  ),
@@ -25789,7 +25922,7 @@ function createRemoteMemoryStore(options) {
25789
25922
  return serialized(
25790
25923
  first,
25791
25924
  () => serialized(second, async () => {
25792
- const [old, next] = await Promise.all([live(id2), live(supersededById)]);
25925
+ const [old, next] = await Promise.all([live2(id2), live2(supersededById)]);
25793
25926
  if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
25794
25927
  if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
25795
25928
  const saved = await persistence.putMany([
@@ -25810,7 +25943,7 @@ function createRemoteMemoryStore(options) {
25810
25943
  (memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
25811
25944
  ),
25812
25945
  restore: (id2) => serialized(id2, async () => {
25813
- const record2 = await live(id2);
25946
+ const record2 = await live2(id2);
25814
25947
  if (!record2) return false;
25815
25948
  if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
25816
25949
  return true;
@@ -32956,6 +33089,7 @@ function useChatStorage(options) {
32956
33089
  };
32957
33090
  }
32958
33091
  export {
33092
+ ANUMA_CONVERSATION_ID,
32959
33093
  CHUNKS_DISCARDED_ORIGIN,
32960
33094
  Conversation as ChatConversation,
32961
33095
  Message as ChatMessage,
@@ -33015,6 +33149,8 @@ export {
33015
33149
  WALLET_PAYMENT_TOOL_NAME,
33016
33150
  WalletPoller,
33017
33151
  addConversationMemoriesOp,
33152
+ anumaLastReadSortKey,
33153
+ anumaTurnContent,
33018
33154
  archiveVaultMemoryOp,
33019
33155
  assembleMemoryContext,
33020
33156
  attachFileContextToLastUserMessage,
@@ -33048,6 +33184,7 @@ export {
33048
33184
  consoleLogger,
33049
33185
  conversationMemoryToStored,
33050
33186
  cosineInt8,
33187
+ countUnreadAnumaTurns,
33051
33188
  createAutoExtractor,
33052
33189
  createChunkVectorCache,
33053
33190
  createCryptoPricePreProcessor,
@@ -33096,6 +33233,7 @@ export {
33096
33233
  embedMessage,
33097
33234
  encodeChunkVector,
33098
33235
  encryptToolCallEventsOp,
33236
+ ensureAnumaConversation,
33099
33237
  ensureDefaultFoldersOp,
33100
33238
  exchangeNotionCode,
33101
33239
  extractAndLinkEntitiesForMemoriesOp,
@@ -33136,6 +33274,7 @@ export {
33136
33274
  isRerankerAvailable,
33137
33275
  loadSettings,
33138
33276
  localChatBackend,
33277
+ markAnumaRead,
33139
33278
  maskScopedEmbeddingCache,
33140
33279
  maxVaultAttachmentBytes,
33141
33280
  memoryCipher,
@@ -33151,6 +33290,7 @@ export {
33151
33290
  quantizeEmbedding,
33152
33291
  queueManager,
33153
33292
  rankProfileCandidates,
33293
+ readAnumaTurn,
33154
33294
  recall,
33155
33295
  reencryptMemoryField,
33156
33296
  reflect,