@anuma/sdk 10.8.0 → 10.10.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.
@@ -266,17 +266,17 @@ async function callPortalJsonCompletion(req) {
266
266
  if (autoUpgraded) endpoint = endpointForTransport(endpoint, transport);
267
267
  assertTransportMatchesEndpoint(transport, endpoint);
268
268
  }
269
- const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
269
+ const maxAttempts2 = Math.max(1, req.maxAttempts ?? 3);
270
270
  const startedAt = Date.now();
271
271
  const deadlineAt = req.totalTimeoutMs === void 0 ? void 0 : startedAt + req.totalTimeoutMs;
272
272
  const overBudget = () => deadlineAt !== void 0 && Date.now() >= deadlineAt;
273
273
  let lastFailure;
274
274
  let reinforce = false;
275
275
  const giveUp = () => {
276
- req.onFailure?.(lastFailure ?? { reason: "network", attempts: maxAttempts });
276
+ req.onFailure?.(lastFailure ?? { reason: "network", attempts: maxAttempts2 });
277
277
  return null;
278
278
  };
279
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
279
+ for (let attempt = 1; attempt <= maxAttempts2; attempt++) {
280
280
  if (attempt > 1 && overBudget()) {
281
281
  log.warn(`[${req.tag}] over time budget before attempt ${attempt}, giving up`);
282
282
  lastFailure = { reason: "time-budget-exhausted", attempts: attempt - 1 };
@@ -308,20 +308,20 @@ async function callPortalJsonCompletion(req) {
308
308
  log.warn(`[${req.tag}] ${outcome2.reason}`);
309
309
  return giveUp();
310
310
  }
311
- if (attempt >= maxAttempts) {
312
- log.warn(`[${req.tag}] ${outcome2.reason} \u2014 attempt ${attempt}/${maxAttempts}, giving up`);
311
+ if (attempt >= maxAttempts2) {
312
+ log.warn(`[${req.tag}] ${outcome2.reason} \u2014 attempt ${attempt}/${maxAttempts2}, giving up`);
313
313
  break;
314
314
  }
315
315
  const backoff = (req.backoffMs ?? defaultBackoffMs)(attempt);
316
316
  const delay = Math.max(backoff, outcome2.retryAfterMs ?? 0);
317
317
  if (overBudget() || req.totalTimeoutMs !== void 0 && Date.now() - startedAt + delay >= req.totalTimeoutMs) {
318
318
  log.warn(
319
- `[${req.tag}] ${outcome2.reason} \u2014 attempt ${attempt}/${maxAttempts}, over time budget, giving up`
319
+ `[${req.tag}] ${outcome2.reason} \u2014 attempt ${attempt}/${maxAttempts2}, over time budget, giving up`
320
320
  );
321
321
  lastFailure = { reason: "time-budget-exhausted", attempts: attempt };
322
322
  break;
323
323
  }
324
- log.warn(`[${req.tag}] ${outcome2.reason} \u2014 attempt ${attempt}/${maxAttempts}, retrying`);
324
+ log.warn(`[${req.tag}] ${outcome2.reason} \u2014 attempt ${attempt}/${maxAttempts2}, retrying`);
325
325
  if (delay > 0) await sleep(delay);
326
326
  }
327
327
  return giveUp();
@@ -1419,6 +1419,7 @@ CARRY FORWARD UNCHANGED DETAILS (every "update" and "supersede"): a memory can h
1419
1419
  // src/react/index.ts
1420
1420
  var index_exports = {};
1421
1421
  __export(index_exports, {
1422
+ ANUMA_CONVERSATION_ID: () => ANUMA_CONVERSATION_ID,
1422
1423
  Anuma: () => Anuma,
1423
1424
  AnumaJsxError: () => AnumaJsxError,
1424
1425
  AnumaShadowIsolationProvider: () => AnumaShadowIsolationProvider,
@@ -1523,6 +1524,8 @@ __export(index_exports, {
1523
1524
  WordProcessor: () => WordProcessor,
1524
1525
  ZipProcessor: () => ZipProcessor,
1525
1526
  addConversationMemoriesOp: () => addConversationMemoriesOp,
1527
+ anumaLastReadSortKey: () => anumaLastReadSortKey,
1528
+ anumaTurnContent: () => anumaTurnContent,
1526
1529
  appFileToStored: () => appFileToStored,
1527
1530
  archiveVaultMemoryOp: () => archiveVaultMemoryOp,
1528
1531
  assembleMemoryContext: () => assembleMemoryContext,
@@ -1562,6 +1565,7 @@ __export(index_exports, {
1562
1565
  consoleLogger: () => consoleLogger,
1563
1566
  conversationMemoryToStored: () => conversationMemoryToStored,
1564
1567
  cosineInt8: () => cosineInt8,
1568
+ countUnreadAnumaTurns: () => countUnreadAnumaTurns,
1565
1569
  createAutoExtractor: () => createAutoExtractor,
1566
1570
  createChunkVectorCache: () => createChunkVectorCache,
1567
1571
  createCryptoPricePreProcessor: () => createCryptoPricePreProcessor,
@@ -1631,6 +1635,7 @@ __export(index_exports, {
1631
1635
  encryptDataBytes: () => encryptDataBytes,
1632
1636
  encryptDataWithKey: () => encryptDataWithKey,
1633
1637
  encryptToolCallEventsOp: () => encryptToolCallEventsOp,
1638
+ ensureAnumaConversation: () => ensureAnumaConversation,
1634
1639
  ensureDefaultFoldersOp: () => ensureDefaultFoldersOp,
1635
1640
  expandToolSetsAdditive: () => expandToolSetsAdditive,
1636
1641
  exportElementToPdf: () => exportElementToPdf,
@@ -1741,6 +1746,7 @@ __export(index_exports, {
1741
1746
  listActiveStreams: () => listActiveStreams,
1742
1747
  loadSettings: () => loadSettings,
1743
1748
  localChatBackend: () => localChatBackend,
1749
+ markAnumaRead: () => markAnumaRead,
1744
1750
  maskScopedEmbeddingCache: () => maskScopedEmbeddingCache,
1745
1751
  maxVaultAttachmentBytes: () => maxVaultAttachmentBytes,
1746
1752
  mediaToStored: () => mediaToStored,
@@ -1766,6 +1772,7 @@ __export(index_exports, {
1766
1772
  quantizeEmbedding: () => quantizeEmbedding,
1767
1773
  queueManager: () => queueManager,
1768
1774
  rankProfileCandidates: () => rankProfileCandidates,
1775
+ readAnumaTurn: () => readAnumaTurn,
1769
1776
  readEncryptedFile: () => readEncryptedFile,
1770
1777
  recall: () => recall,
1771
1778
  reencryptMemoryField: () => reencryptMemoryField,
@@ -5388,7 +5395,7 @@ async function updateMessageErrorOp(ctx, uniqueId, error) {
5388
5395
  }
5389
5396
  await ctx.database.write(async () => {
5390
5397
  await message.update((msg) => {
5391
- msg._setRaw("error", error);
5398
+ msg._setRaw("error", error ?? "");
5392
5399
  });
5393
5400
  });
5394
5401
  return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
@@ -8025,17 +8032,17 @@ async function createRemoteMemoryPersistence(options) {
8025
8032
  expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
8026
8033
  if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
8027
8034
  throw new Error("expectedVersion must be a nonnegative integer");
8028
- const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
8035
+ const conflict2 = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
8029
8036
  let existing;
8030
8037
  if (expectedVersion !== 0 && !snapshot) {
8031
8038
  try {
8032
8039
  existing = memoryRecord(await request(path, {}, signal));
8033
8040
  } catch (error) {
8034
- if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
8041
+ if (error instanceof RemoteMemoryError && error.status === 404) throw conflict2();
8035
8042
  throw error;
8036
8043
  }
8037
8044
  }
8038
- if (existing && existing.version !== expectedVersion) throw conflict();
8045
+ if (existing && existing.version !== expectedVersion) throw conflict2();
8039
8046
  const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
8040
8047
  const reusableContent = snapshot?.encryptedContent ?? existing?.memory.content;
8041
8048
  const content = reusableContent && (snapshot?.content ?? decoded?.memory.content) === memory.content ? reusableContent : await encryptField2(memory.content);
@@ -8347,6 +8354,67 @@ async function openInboxItem(item, keyPair) {
8347
8354
  }
8348
8355
  return opened;
8349
8356
  }
8357
+ function inboxReplaces(row, opened) {
8358
+ if (row.error) return true;
8359
+ return row.wasStopped === true && opened.status === "completed";
8360
+ }
8361
+ async function clearTurnErrors(backend, answer) {
8362
+ const parentId = answer.parentMessageId;
8363
+ if (parentId) {
8364
+ const [parent] = await backend.getMessagesByIds([parentId]);
8365
+ if (parent?.error) await backend.updateMessageError(parentId, null);
8366
+ }
8367
+ if (!answer.error) return answer;
8368
+ return await backend.updateMessageError(answer.uniqueId, null) ?? answer;
8369
+ }
8370
+ async function deliverInboxAnswers(options) {
8371
+ const { inbox, keyPair, backend, store } = options;
8372
+ const results = [];
8373
+ for (const item of await inbox.list()) {
8374
+ let opened;
8375
+ try {
8376
+ opened = await openInboxItem(item, keyPair);
8377
+ } catch (err) {
8378
+ results.push({
8379
+ id: item.id,
8380
+ conversationId: null,
8381
+ status: "unreadable",
8382
+ assistantMessage: null,
8383
+ error: err instanceof Error ? err.message : String(err)
8384
+ });
8385
+ continue;
8386
+ }
8387
+ const base = { id: item.id, conversationId: opened.conversation_id };
8388
+ try {
8389
+ const messageId = opened.assistant_message_id ?? `msg_bg_${opened.inference_id}`;
8390
+ const [found] = await backend.getMessagesByIds([messageId]);
8391
+ const existing = found && inboxReplaces(found, opened) ? void 0 : found;
8392
+ if (!found) {
8393
+ const parent = opened.parent_message_id;
8394
+ const ownsTurn = parent ? (await backend.getMessagesByIds([parent])).length > 0 : await backend.getConversation(opened.conversation_id) !== null;
8395
+ if (!ownsTurn) {
8396
+ results.push({ ...base, status: "elsewhere", assistantMessage: null });
8397
+ continue;
8398
+ }
8399
+ }
8400
+ const stored2 = existing ?? await store(opened, messageId);
8401
+ await inbox.remove(item.id);
8402
+ results.push({
8403
+ ...base,
8404
+ status: existing ? "delivered" : "stored",
8405
+ assistantMessage: stored2
8406
+ });
8407
+ } catch (err) {
8408
+ results.push({
8409
+ ...base,
8410
+ status: "retry",
8411
+ assistantMessage: null,
8412
+ error: err instanceof Error ? err.message : String(err)
8413
+ });
8414
+ }
8415
+ }
8416
+ return results;
8417
+ }
8350
8418
 
8351
8419
  // src/lib/chat/reservationReceipts.ts
8352
8420
  var ACTIONS = [
@@ -9838,6 +9906,13 @@ function createErrorResult(message, onError) {
9838
9906
  function isAbortError(err) {
9839
9907
  return err instanceof Error && err.name === "AbortError";
9840
9908
  }
9909
+ var ProviderStreamError = class extends Error {
9910
+ constructor(message, code) {
9911
+ super(message);
9912
+ this.name = "ProviderStreamError";
9913
+ this.code = code;
9914
+ }
9915
+ };
9841
9916
  function getInStreamErrorMessage(chunk) {
9842
9917
  if (!chunk || typeof chunk !== "object") return null;
9843
9918
  const obj = chunk;
@@ -10124,7 +10199,7 @@ var CompletionsStrategy = class {
10124
10199
  processStreamChunk(chunk, accumulator) {
10125
10200
  const result = { content: null, thinking: null };
10126
10201
  const inStreamErr = getInStreamErrorMessage(chunk);
10127
- if (inStreamErr) throw new Error(inStreamErr);
10202
+ if (inStreamErr) throw new ProviderStreamError(inStreamErr);
10128
10203
  const rawChunk = chunk;
10129
10204
  const typedChunk = rawChunk.response && rawChunk.type === "response" ? rawChunk.response : chunk;
10130
10205
  if (typedChunk.id && !accumulator.responseId) {
@@ -10975,7 +11050,7 @@ var ResponsesStrategy = class {
10975
11050
  const result = { content: null, thinking: null };
10976
11051
  const typedChunk = chunk;
10977
11052
  const inStreamErr = getInStreamErrorMessage(chunk);
10978
- if (inStreamErr) throw new Error(inStreamErr);
11053
+ if (inStreamErr) throw new ProviderStreamError(inStreamErr);
10979
11054
  if (typedChunk.type === "response.failed") {
10980
11055
  const resp = typedChunk.response;
10981
11056
  const err = resp?.error;
@@ -10992,9 +11067,12 @@ var ResponsesStrategy = class {
10992
11067
  }
10993
11068
  }
10994
11069
  const label = code ? `[${code}] ` : "";
10995
- throw new Error(`${label}${message || "Upstream request failed"}`);
11070
+ throw new ProviderStreamError(
11071
+ `${label}${message || "Upstream request failed"}`,
11072
+ code || void 0
11073
+ );
10996
11074
  }
10997
- throw new Error("Upstream request failed (response.failed)");
11075
+ throw new ProviderStreamError("Upstream request failed (response.failed)");
10998
11076
  }
10999
11077
  if (typedChunk.type === "response" && typedChunk.response) {
11000
11078
  const resp = typedChunk.response;
@@ -11618,13 +11696,6 @@ function isRetriableStreamError(err) {
11618
11696
  if (msg.includes("connection refused") || msg.includes("connect error")) return true;
11619
11697
  return false;
11620
11698
  }
11621
- var ProviderStreamError = class extends Error {
11622
- constructor(message, code) {
11623
- super(message);
11624
- this.name = "ProviderStreamError";
11625
- this.code = code;
11626
- }
11627
- };
11628
11699
  function extractProviderStreamError(chunk) {
11629
11700
  if (!chunk || typeof chunk !== "object") return null;
11630
11701
  const errField = chunk.error;
@@ -12005,6 +12076,7 @@ async function runToolLoop(options) {
12005
12076
  thinking: redactor.deAnonymize(acc.thinking)
12006
12077
  }) : strategy.buildFinalResponse(acc);
12007
12078
  const finalContentText = (acc) => redactor ? redactor.deAnonymize(acc.content) : acc.content;
12079
+ let streamingAccumulator = null;
12008
12080
  try {
12009
12081
  let sseError = null;
12010
12082
  let apiTools = toolsToApiFormat(tools, resolved);
@@ -12156,6 +12228,7 @@ async function runToolLoop(options) {
12156
12228
  }
12157
12229
  });
12158
12230
  accumulator = createStreamAccumulator(model || void 0);
12231
+ streamingAccumulator = accumulator;
12159
12232
  contentSmoother = new StreamSmoother((text16) => {
12160
12233
  if (emitData) emitData(text16);
12161
12234
  }, smoothing);
@@ -12666,6 +12739,7 @@ Executing tool: ${toolInfo}
12666
12739
  }
12667
12740
  });
12668
12741
  currentAccumulator = createStreamAccumulator(model || void 0);
12742
+ streamingAccumulator = currentAccumulator;
12669
12743
  contContentSmoother = new StreamSmoother((text16) => {
12670
12744
  if (emitData) emitData(text16);
12671
12745
  }, smoothing);
@@ -12863,7 +12937,7 @@ Executing tool: ${toolInfo}
12863
12937
  const statusCode = err instanceof Error && "statusCode" in err ? err.statusCode : void 0;
12864
12938
  const connectionLost = !(err instanceof ProviderStreamError) && !(err instanceof SseError);
12865
12939
  return {
12866
- data: null,
12940
+ data: connectionLost && streamingAccumulator ? buildResponseFinal(streamingAccumulator) : null,
12867
12941
  error: errorMsg,
12868
12942
  statusCode,
12869
12943
  ...connectionLost ? { connectionLost: true } : {}
@@ -13208,119 +13282,19 @@ function createWebSearchPreProcessor(options = {}) {
13208
13282
  };
13209
13283
  }
13210
13284
 
13211
- // src/lib/db/chat/summaryOperations.ts
13212
- var import_watermelondb5 = require("@nozbe/watermelondb");
13213
- init_logger();
13214
- function createSummaryContext(database, encryption = {}) {
13215
- return {
13216
- ...encryption,
13217
- database,
13218
- summariesCollection: database.get("conversation_summaries")
13219
- };
13220
- }
13221
- function modelToStored(record2, summary) {
13222
- return {
13223
- uniqueId: record2.id,
13224
- conversationId: record2.conversationId,
13225
- summary,
13226
- summarizedUpTo: record2.summarizedUpTo,
13227
- tokenCount: record2.tokenCount,
13228
- createdAt: record2.createdAt,
13229
- updatedAt: record2.updatedAt
13230
- };
13231
- }
13232
- async function getConversationSummaryOp(ctx, conversationId) {
13233
- const results = await ctx.summariesCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId)).fetch();
13234
- if (results.length === 0) return null;
13235
- const record2 = results[0];
13236
- const stored2 = modelToStored(record2, record2.summary);
13237
- if (ctx.walletAddress && isEncrypted(stored2.summary)) {
13238
- if (ctx.signMessage) {
13239
- try {
13240
- await requestEncryptionKey(ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13241
- } catch (error) {
13242
- getLogger().warn("Failed to request the encryption key for the summary:", error);
13243
- }
13244
- }
13245
- stored2.summary = await decryptField(stored2.summary, ctx.walletAddress);
13246
- } else if (ctx.walletAddress && ctx.signMessage && stored2.summary) {
13247
- try {
13248
- const encryptedSummary = await encryptField(
13249
- stored2.summary,
13250
- ctx.walletAddress,
13251
- ctx.signMessage,
13252
- ctx.embeddedWalletSigner
13253
- );
13254
- await ctx.database.write(async () => {
13255
- const current = await ctx.summariesCollection.query(import_watermelondb5.Q.where("id", record2.id)).fetch();
13256
- if (current[0]?.summary === stored2.summary) {
13257
- await current[0].update((rec) => {
13258
- rec.summary = encryptedSummary;
13259
- });
13260
- }
13261
- });
13262
- } catch (error) {
13263
- getLogger().warn("Failed to encrypt the legacy summary:", error);
13264
- }
13285
+ // src/lib/chatStore/types.ts
13286
+ var ChatStoreError = class extends Error {
13287
+ constructor(message, status, code, retryAfterMs) {
13288
+ super(message);
13289
+ this.status = status;
13290
+ this.code = code;
13291
+ this.retryAfterMs = retryAfterMs;
13292
+ this.name = "ChatStoreError";
13265
13293
  }
13266
- return stored2;
13267
- }
13268
- async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
13269
- const revision2 = getConversationRevision(ctx.database, conversationId);
13270
- let record2;
13271
- const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
13272
- await ctx.database.write(async () => {
13273
- assertConversationRevision(ctx.database, conversationId, revision2);
13274
- const existing = await ctx.summariesCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId)).fetch();
13275
- if (existing.length > 0) {
13276
- record2 = await existing[0].update((rec) => {
13277
- rec.summary = encryptedSummary;
13278
- rec.summarizedUpTo = summarizedUpTo;
13279
- rec.tokenCount = tokenCount;
13280
- });
13281
- } else {
13282
- record2 = await ctx.summariesCollection.create((rec) => {
13283
- rec.conversationId = conversationId;
13284
- rec.summary = encryptedSummary;
13285
- rec.summarizedUpTo = summarizedUpTo;
13286
- rec.tokenCount = tokenCount;
13287
- });
13288
- }
13289
- });
13290
- return modelToStored(record2, summary);
13291
- }
13292
- async function deleteConversationSummaryOp(ctx, conversationId) {
13293
- await ctx.database.write(async () => {
13294
- const existing = await ctx.summariesCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId)).fetch();
13295
- for (const record2 of existing) {
13296
- await record2.destroyPermanently();
13297
- }
13298
- });
13299
- }
13300
-
13301
- // src/lib/db/conversationMemory/models.ts
13302
- var import_watermelondb6 = require("@nozbe/watermelondb");
13303
- var import_decorators2 = require("@nozbe/watermelondb/decorators");
13304
- var ConversationMemory = class extends import_watermelondb6.Model {
13305
13294
  };
13306
- ConversationMemory.table = "conversation_memory";
13307
- ConversationMemory.associations = {};
13308
- __decorateClass([
13309
- (0, import_decorators2.text)("conversation_id")
13310
- ], ConversationMemory.prototype, "conversationId", 2);
13311
- __decorateClass([
13312
- (0, import_decorators2.text)("memory_id")
13313
- ], ConversationMemory.prototype, "memoryId", 2);
13314
- __decorateClass([
13315
- (0, import_decorators2.field)("score")
13316
- ], ConversationMemory.prototype, "score", 2);
13317
- __decorateClass([
13318
- import_decorators2.readonly,
13319
- (0, import_decorators2.date)("created_at")
13320
- ], ConversationMemory.prototype, "createdAt", 2);
13321
13295
 
13322
13296
  // src/lib/db/conversationMemory/operations.ts
13323
- var import_watermelondb7 = require("@nozbe/watermelondb");
13297
+ var import_watermelondb5 = require("@nozbe/watermelondb");
13324
13298
  var MAX_PER_CONVERSATION = 200;
13325
13299
  function conversationMemoryToStored(row) {
13326
13300
  return {
@@ -13335,7 +13309,7 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
13335
13309
  if (!conversationId || items.length === 0) return;
13336
13310
  const now = Date.now();
13337
13311
  await ctx.database.write(async () => {
13338
- const existing = await ctx.conversationMemoryCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId), import_watermelondb7.Q.sortBy("created_at", import_watermelondb7.Q.asc)).fetch();
13312
+ const existing = await ctx.conversationMemoryCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId), import_watermelondb5.Q.sortBy("created_at", import_watermelondb5.Q.asc)).fetch();
13339
13313
  const seen = new Set(existing.map((r) => r.memoryId));
13340
13314
  const batchSeen = /* @__PURE__ */ new Set();
13341
13315
  const deduped = [];
@@ -13372,7 +13346,7 @@ async function recordConversationMemoriesOp(ctx, conversationId, items, now = Da
13372
13346
  if (!conversationId || turn.size === 0) return;
13373
13347
  const kept = new Map([...turn].slice(-MAX_PER_CONVERSATION));
13374
13348
  await ctx.database.write(async () => {
13375
- const existing = await ctx.conversationMemoryCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId), import_watermelondb7.Q.sortBy("created_at", import_watermelondb7.Q.asc)).fetch();
13349
+ const existing = await ctx.conversationMemoryCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId), import_watermelondb5.Q.sortBy("created_at", import_watermelondb5.Q.asc)).fetch();
13376
13350
  const earlier = existing.filter((r) => !turn.has(r.memoryId));
13377
13351
  const linked = new Set(existing.map((r) => r.memoryId));
13378
13352
  await ctx.database.batch(
@@ -13397,13 +13371,13 @@ async function recordConversationMemoriesOp(ctx, conversationId, items, now = Da
13397
13371
  }
13398
13372
  async function getConversationMemoriesOp(ctx, conversationId) {
13399
13373
  if (!conversationId) return [];
13400
- const rows = await ctx.conversationMemoryCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId), import_watermelondb7.Q.sortBy("created_at", import_watermelondb7.Q.asc)).fetch();
13374
+ const rows = await ctx.conversationMemoryCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId), import_watermelondb5.Q.sortBy("created_at", import_watermelondb5.Q.asc)).fetch();
13401
13375
  return rows.map(conversationMemoryToStored);
13402
13376
  }
13403
13377
  async function clearConversationMemoriesOp(ctx, conversationId) {
13404
13378
  if (!conversationId) return;
13405
13379
  await ctx.database.write(async () => {
13406
- const rows = await ctx.conversationMemoryCollection.query(import_watermelondb7.Q.where("conversation_id", conversationId)).fetch();
13380
+ const rows = await ctx.conversationMemoryCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId)).fetch();
13407
13381
  if (rows.length === 0) return;
13408
13382
  await ctx.database.batch(...rows.map((r) => r.prepareDestroyPermanently()));
13409
13383
  });
@@ -13418,15 +13392,37 @@ var maxChunks = 16;
13418
13392
  var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
13419
13393
  var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
13420
13394
  var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
13395
+ var maxBubbles = 3;
13396
+ var maxTurnIdBytes = 128;
13397
+ var maxBubbleBytes = 16384;
13398
+ var anumaOrigins = /* @__PURE__ */ new Set(["intro", "reply"]);
13421
13399
  function plain(value) {
13422
13400
  return JSON.parse(JSON.stringify(value ?? {}));
13423
13401
  }
13424
- function text4(value) {
13402
+ function text3(value) {
13425
13403
  return typeof value === "string" ? value : void 0;
13426
13404
  }
13427
13405
  function number(value) {
13428
13406
  return typeof value === "number" ? value : void 0;
13429
13407
  }
13408
+ function readAnumaTurn(value) {
13409
+ if (!isObject(value)) return void 0;
13410
+ const { turnId, bubbles, origin } = value;
13411
+ if (typeof turnId !== "string" || turnId.length === 0 || new TextEncoder().encode(turnId).length > maxTurnIdBytes)
13412
+ return void 0;
13413
+ 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))
13414
+ return void 0;
13415
+ if (origin !== void 0 && (typeof origin !== "string" || !anumaOrigins.has(origin)))
13416
+ return void 0;
13417
+ return {
13418
+ turnId,
13419
+ ...bubbles !== void 0 ? { bubbles: [...bubbles] } : {},
13420
+ ...origin !== void 0 ? { origin } : {}
13421
+ };
13422
+ }
13423
+ function isObject(value) {
13424
+ return value !== null && typeof value === "object" && !Array.isArray(value);
13425
+ }
13430
13426
  function conversationSortKey(data, createdAt) {
13431
13427
  const pinnedAt = number(data.pinnedAt);
13432
13428
  if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
@@ -13447,12 +13443,12 @@ function conversationContext(data) {
13447
13443
  }
13448
13444
  function toConversation(record2) {
13449
13445
  const pinnedAt = number(record2.data.pinnedAt);
13450
- const projectId = text4(record2.data.projectId);
13446
+ const projectId = text3(record2.data.projectId);
13451
13447
  const context = conversationContext(record2.data);
13452
13448
  return {
13453
13449
  uniqueId: record2.id,
13454
13450
  conversationId: record2.id,
13455
- title: text4(record2.data.title) ?? "",
13451
+ title: text3(record2.data.title) ?? "",
13456
13452
  ...projectId ? { projectId } : {},
13457
13453
  createdAt: new Date(record2.createdAt),
13458
13454
  updatedAt: new Date(record2.updatedAt),
@@ -13461,18 +13457,28 @@ function toConversation(record2) {
13461
13457
  ...context ? { context } : {}
13462
13458
  };
13463
13459
  }
13460
+ function anumaTurnData(value) {
13461
+ if (value === void 0) return void 0;
13462
+ const turn = readAnumaTurn(value);
13463
+ if (!turn) throw new ChatStoreError("Invalid Anuma turn", 0, "invalid_record");
13464
+ return turn;
13465
+ }
13464
13466
  function messageData(options) {
13465
- return plain(
13466
- Object.fromEntries(
13467
+ const anuma = anumaTurnData(options.anuma);
13468
+ return plain({
13469
+ ...Object.fromEntries(
13467
13470
  Object.entries(options).filter(
13468
- ([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
13471
+ ([key3, value]) => key3 !== "anuma" && !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
13469
13472
  )
13470
- )
13471
- );
13473
+ ),
13474
+ ...anuma ? { anuma } : {}
13475
+ });
13472
13476
  }
13473
13477
  function toMessage(record2) {
13474
- const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
13478
+ const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } = record2.data;
13479
+ const anuma = readAnumaTurn(rawAnuma);
13475
13480
  return {
13481
+ ...anuma ? { anuma } : {},
13476
13482
  ...fields,
13477
13483
  uniqueId: record2.id,
13478
13484
  messageId: record2.sortKey,
@@ -13486,20 +13492,20 @@ function chunkOffsets(record2) {
13486
13492
  return Array.isArray(offsets) ? offsets : void 0;
13487
13493
  }
13488
13494
  function toSkeletons(records) {
13489
- const roleById = new Map(records.map((r) => [r.id, text4(r.data.role)]));
13495
+ const roleById = new Map(records.map((r) => [r.id, text3(r.data.role)]));
13490
13496
  return records.map((r) => {
13491
- const parentMessageId = text4(r.data.parentMessageId);
13492
- const model = text4(r.data.model);
13497
+ const parentMessageId = text3(r.data.parentMessageId);
13498
+ const model = text3(r.data.model);
13493
13499
  const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
13494
13500
  return {
13495
13501
  uniqueId: r.id,
13496
13502
  messageId: r.sortKey,
13497
13503
  conversationId: r.conversationId,
13498
- role: text4(r.data.role) ?? "",
13504
+ role: text3(r.data.role) ?? "",
13499
13505
  createdAt: new Date(r.createdAt),
13500
13506
  ...parentMessageId ? { parentMessageId } : {},
13501
13507
  ...model ? { model } : {},
13502
- ...artifact ? { content: text4(r.data.content) ?? "" } : {}
13508
+ ...artifact ? { content: text3(r.data.content) ?? "" } : {}
13503
13509
  };
13504
13510
  });
13505
13511
  }
@@ -13507,8 +13513,8 @@ function toSummary(record2) {
13507
13513
  return {
13508
13514
  uniqueId: record2.id,
13509
13515
  conversationId: record2.id,
13510
- summary: text4(record2.data.summary) ?? "",
13511
- summarizedUpTo: text4(record2.data.summarizedUpTo) ?? "",
13516
+ summary: text3(record2.data.summary) ?? "",
13517
+ summarizedUpTo: text3(record2.data.summarizedUpTo) ?? "",
13512
13518
  tokenCount: number(record2.data.tokenCount) ?? 0,
13513
13519
  createdAt: new Date(record2.createdAt),
13514
13520
  updatedAt: new Date(record2.updatedAt)
@@ -13559,7 +13565,7 @@ function fitRecord(record2) {
13559
13565
  delete data[field10];
13560
13566
  truncated.push(field10);
13561
13567
  }
13562
- const content = text4(data.content) ?? "";
13568
+ const content = text3(data.content) ?? "";
13563
13569
  const over = bytes({ ...record2, data }) - recordBudgetBytes;
13564
13570
  if (over > 0) {
13565
13571
  const encoded = new TextEncoder().encode(content);
@@ -13603,6 +13609,216 @@ function fitChunks(chunks3) {
13603
13609
  return out;
13604
13610
  }
13605
13611
 
13612
+ // src/lib/chatStore/anuma.ts
13613
+ var ANUMA_CONVERSATION_ID = "anuma-1on1";
13614
+ var maxAttempts = 3;
13615
+ function anumaTurnContent(bubbles) {
13616
+ return bubbles.join("\n\n");
13617
+ }
13618
+ function anumaLastReadSortKey(conversation) {
13619
+ const record2 = conversation && "record" in conversation ? conversation.record : conversation;
13620
+ const state = record2?.data.anuma;
13621
+ if (!isObject(state)) return 0;
13622
+ const sortKey = state.lastReadSortKey;
13623
+ return Number.isSafeInteger(sortKey) && sortKey > 0 ? sortKey : 0;
13624
+ }
13625
+ function conflict(error) {
13626
+ return error instanceof ChatStoreError && error.code === "version_conflict";
13627
+ }
13628
+ function live(snapshot) {
13629
+ if (snapshot?.record.isDeleted)
13630
+ throw new ChatStoreError("Anuma conversation was deleted", 409, "conversation_deleted");
13631
+ return snapshot;
13632
+ }
13633
+ async function ensureAnumaConversation(store, options = {}) {
13634
+ const existing = live(await store.get("conversation", ANUMA_CONVERSATION_ID, options.signal));
13635
+ if (existing) return existing;
13636
+ const at = (options.now ?? Date.now)();
13637
+ const data = plain({ title: "Anuma", lastActivityAt: at, anuma: { lastReadSortKey: 0 } });
13638
+ try {
13639
+ const [created] = await store.putMany(
13640
+ [
13641
+ {
13642
+ expectedVersion: 0,
13643
+ record: {
13644
+ kind: "conversation",
13645
+ id: ANUMA_CONVERSATION_ID,
13646
+ conversationId: "",
13647
+ sortKey: conversationSortKey(data, at),
13648
+ createdAt: at,
13649
+ updatedAt: at,
13650
+ isDeleted: false,
13651
+ data
13652
+ }
13653
+ }
13654
+ ],
13655
+ options.signal
13656
+ );
13657
+ return created;
13658
+ } catch (error) {
13659
+ if (!conflict(error)) throw error;
13660
+ const winner = live(await store.get("conversation", ANUMA_CONVERSATION_ID, options.signal));
13661
+ if (!winner) throw error;
13662
+ return winner;
13663
+ }
13664
+ }
13665
+ async function markAnumaRead(store, sortKey, options = {}) {
13666
+ if (!Number.isSafeInteger(sortKey) || sortKey < 0)
13667
+ throw new ChatStoreError("Invalid Anuma read marker", 0, "invalid_record");
13668
+ const now = options.now ?? Date.now;
13669
+ for (let attempt = 1; ; attempt++) {
13670
+ const current = await ensureAnumaConversation(store, options);
13671
+ const read = anumaLastReadSortKey(current);
13672
+ if (sortKey <= read) return current;
13673
+ const record2 = current.record;
13674
+ const state = isObject(record2.data.anuma) ? record2.data.anuma : {};
13675
+ const data = plain({ ...record2.data, anuma: { ...state, lastReadSortKey: sortKey } });
13676
+ try {
13677
+ const [written] = await store.putMany(
13678
+ [
13679
+ {
13680
+ expectedVersion: current.version,
13681
+ record: {
13682
+ ...record2,
13683
+ data,
13684
+ sortKey: conversationSortKey(data, record2.createdAt),
13685
+ updatedAt: Math.max(record2.updatedAt, now())
13686
+ }
13687
+ }
13688
+ ],
13689
+ options.signal
13690
+ );
13691
+ return written;
13692
+ } catch (error) {
13693
+ if (!conflict(error) || attempt >= maxAttempts) throw error;
13694
+ }
13695
+ }
13696
+ }
13697
+ function countUnreadAnumaTurns(messages, lastReadSortKey) {
13698
+ const answered = Math.max(
13699
+ 0,
13700
+ ...messages.filter((m) => m.role === "user").map((m) => m.messageId)
13701
+ );
13702
+ const floor = Math.max(lastReadSortKey, answered);
13703
+ const turns = /* @__PURE__ */ new Set();
13704
+ for (const m of messages) {
13705
+ if (m.role !== "assistant" || m.messageId <= floor) continue;
13706
+ turns.add(m.anuma?.turnId ? `turn:${m.anuma.turnId}` : `message:${m.uniqueId}`);
13707
+ }
13708
+ return turns.size;
13709
+ }
13710
+
13711
+ // src/lib/db/chat/summaryOperations.ts
13712
+ var import_watermelondb6 = require("@nozbe/watermelondb");
13713
+ init_logger();
13714
+ function createSummaryContext(database, encryption = {}) {
13715
+ return {
13716
+ ...encryption,
13717
+ database,
13718
+ summariesCollection: database.get("conversation_summaries")
13719
+ };
13720
+ }
13721
+ function modelToStored(record2, summary) {
13722
+ return {
13723
+ uniqueId: record2.id,
13724
+ conversationId: record2.conversationId,
13725
+ summary,
13726
+ summarizedUpTo: record2.summarizedUpTo,
13727
+ tokenCount: record2.tokenCount,
13728
+ createdAt: record2.createdAt,
13729
+ updatedAt: record2.updatedAt
13730
+ };
13731
+ }
13732
+ async function getConversationSummaryOp(ctx, conversationId) {
13733
+ const results = await ctx.summariesCollection.query(import_watermelondb6.Q.where("conversation_id", conversationId)).fetch();
13734
+ if (results.length === 0) return null;
13735
+ const record2 = results[0];
13736
+ const stored2 = modelToStored(record2, record2.summary);
13737
+ if (ctx.walletAddress && isEncrypted(stored2.summary)) {
13738
+ if (ctx.signMessage) {
13739
+ try {
13740
+ await requestEncryptionKey(ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13741
+ } catch (error) {
13742
+ getLogger().warn("Failed to request the encryption key for the summary:", error);
13743
+ }
13744
+ }
13745
+ stored2.summary = await decryptField(stored2.summary, ctx.walletAddress);
13746
+ } else if (ctx.walletAddress && ctx.signMessage && stored2.summary) {
13747
+ try {
13748
+ const encryptedSummary = await encryptField(
13749
+ stored2.summary,
13750
+ ctx.walletAddress,
13751
+ ctx.signMessage,
13752
+ ctx.embeddedWalletSigner
13753
+ );
13754
+ await ctx.database.write(async () => {
13755
+ const current = await ctx.summariesCollection.query(import_watermelondb6.Q.where("id", record2.id)).fetch();
13756
+ if (current[0]?.summary === stored2.summary) {
13757
+ await current[0].update((rec) => {
13758
+ rec.summary = encryptedSummary;
13759
+ });
13760
+ }
13761
+ });
13762
+ } catch (error) {
13763
+ getLogger().warn("Failed to encrypt the legacy summary:", error);
13764
+ }
13765
+ }
13766
+ return stored2;
13767
+ }
13768
+ async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
13769
+ const revision2 = getConversationRevision(ctx.database, conversationId);
13770
+ let record2;
13771
+ const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
13772
+ await ctx.database.write(async () => {
13773
+ assertConversationRevision(ctx.database, conversationId, revision2);
13774
+ const existing = await ctx.summariesCollection.query(import_watermelondb6.Q.where("conversation_id", conversationId)).fetch();
13775
+ if (existing.length > 0) {
13776
+ record2 = await existing[0].update((rec) => {
13777
+ rec.summary = encryptedSummary;
13778
+ rec.summarizedUpTo = summarizedUpTo;
13779
+ rec.tokenCount = tokenCount;
13780
+ });
13781
+ } else {
13782
+ record2 = await ctx.summariesCollection.create((rec) => {
13783
+ rec.conversationId = conversationId;
13784
+ rec.summary = encryptedSummary;
13785
+ rec.summarizedUpTo = summarizedUpTo;
13786
+ rec.tokenCount = tokenCount;
13787
+ });
13788
+ }
13789
+ });
13790
+ return modelToStored(record2, summary);
13791
+ }
13792
+ async function deleteConversationSummaryOp(ctx, conversationId) {
13793
+ await ctx.database.write(async () => {
13794
+ const existing = await ctx.summariesCollection.query(import_watermelondb6.Q.where("conversation_id", conversationId)).fetch();
13795
+ for (const record2 of existing) {
13796
+ await record2.destroyPermanently();
13797
+ }
13798
+ });
13799
+ }
13800
+
13801
+ // src/lib/db/conversationMemory/models.ts
13802
+ var import_watermelondb7 = require("@nozbe/watermelondb");
13803
+ var import_decorators2 = require("@nozbe/watermelondb/decorators");
13804
+ var ConversationMemory = class extends import_watermelondb7.Model {
13805
+ };
13806
+ ConversationMemory.table = "conversation_memory";
13807
+ ConversationMemory.associations = {};
13808
+ __decorateClass([
13809
+ (0, import_decorators2.text)("conversation_id")
13810
+ ], ConversationMemory.prototype, "conversationId", 2);
13811
+ __decorateClass([
13812
+ (0, import_decorators2.text)("memory_id")
13813
+ ], ConversationMemory.prototype, "memoryId", 2);
13814
+ __decorateClass([
13815
+ (0, import_decorators2.field)("score")
13816
+ ], ConversationMemory.prototype, "score", 2);
13817
+ __decorateClass([
13818
+ import_decorators2.readonly,
13819
+ (0, import_decorators2.date)("created_at")
13820
+ ], ConversationMemory.prototype, "createdAt", 2);
13821
+
13606
13822
  // src/lib/chatStore/chatImports.ts
13607
13823
  var importBatch = 100;
13608
13824
  var importChunks = 200;
@@ -13694,17 +13910,6 @@ function batches(records) {
13694
13910
  return out;
13695
13911
  }
13696
13912
 
13697
- // src/lib/chatStore/types.ts
13698
- var ChatStoreError = class extends Error {
13699
- constructor(message, status, code, retryAfterMs) {
13700
- super(message);
13701
- this.status = status;
13702
- this.code = code;
13703
- this.retryAfterMs = retryAfterMs;
13704
- this.name = "ChatStoreError";
13705
- }
13706
- };
13707
-
13708
13913
  // src/lib/chatStore/remote.ts
13709
13914
  var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links", "setting"]);
13710
13915
  var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
@@ -14429,10 +14634,10 @@ async function deletedSinceUpload(store, journal, local, signal) {
14429
14634
  const present = /* @__PURE__ */ new Set([...local.records.map((r) => key(r.record)), ...local.skipped.keys()]);
14430
14635
  const gone = [...journal.keys].filter((k) => !present.has(k));
14431
14636
  if (gone.length === 0) return [];
14432
- const live = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
14433
- const tombstoning = new Set(live.map((s) => key(s.record)));
14637
+ const live2 = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
14638
+ const tombstoning = new Set(live2.map((s) => key(s.record)));
14434
14639
  await journal.drop(gone.filter((k) => !tombstoning.has(k)));
14435
- return live.map(({ record: record2, version }) => {
14640
+ return live2.map(({ record: record2, version }) => {
14436
14641
  const empty = emptied[record2.kind];
14437
14642
  return {
14438
14643
  record: {
@@ -15092,12 +15297,13 @@ var resumableFields = [
15092
15297
  "error",
15093
15298
  "thoughtProcess",
15094
15299
  "thinking",
15095
- "toolCallEvents"
15300
+ "toolCallEvents",
15301
+ "anuma"
15096
15302
  ];
15097
15303
  function resumedFields(options) {
15098
15304
  return plain(
15099
15305
  Object.fromEntries(
15100
- resumableFields.filter((f) => options[f] !== void 0).map((f) => [f, options[f]])
15306
+ resumableFields.filter((f) => options[f] !== void 0).map((f) => [f, f === "anuma" ? anumaTurnData(options.anuma) : options[f]])
15101
15307
  )
15102
15308
  );
15103
15309
  }
@@ -15751,7 +15957,7 @@ function createVaultChatBackend(options) {
15751
15957
  },
15752
15958
  async getConversations(query) {
15753
15959
  await available2();
15754
- return all("conversation").map(toConversation).filter(
15960
+ return all("conversation").filter((record2) => record2.id !== ANUMA_CONVERSATION_ID).map(toConversation).filter(
15755
15961
  (c) => query?.projectId === void 0 || (query.projectId === null ? !c.projectId : c.projectId === query.projectId)
15756
15962
  ).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
15757
15963
  },
@@ -15794,6 +16000,7 @@ function createVaultChatBackend(options) {
15794
16000
  return !!record2 && !record2.isDeleted;
15795
16001
  },
15796
16002
  async deleteConversation(conversationId) {
16003
+ if (conversationId === ANUMA_CONVERSATION_ID) return false;
15797
16004
  const record2 = await conversation(conversationId);
15798
16005
  if (!record2 || record2.isDeleted) return false;
15799
16006
  for (const [k, patch] of pending)
@@ -19864,7 +20071,7 @@ async function countActiveVaultMemoriesOp(ctx) {
19864
20071
  return ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx)).fetchCount();
19865
20072
  }
19866
20073
  async function getVaultMemoryCountsOp(ctx) {
19867
- const [live, archived, quarantined] = await Promise.all([
20074
+ const [live2, archived, quarantined] = await Promise.all([
19868
20075
  countActiveVaultMemoriesOp(ctx),
19869
20076
  ctx.vaultMemoryCollection.query(
19870
20077
  ...baseVaultConditions(ctx, { includeArchived: true }),
@@ -19875,7 +20082,7 @@ async function getVaultMemoryCountsOp(ctx) {
19875
20082
  import_watermelondb24.Q.where("trust_tier", "quarantined")
19876
20083
  ).fetchCount()
19877
20084
  ]);
19878
- return { live, archived, quarantined };
20085
+ return { live: live2, archived, quarantined };
19879
20086
  }
19880
20087
  async function getActiveVaultMemoryIdsOp(ctx, ids) {
19881
20088
  if (ids.length === 0) return /* @__PURE__ */ new Set();
@@ -21249,12 +21456,12 @@ var WalletPoller = class {
21249
21456
  * @param maxAttempts - Maximum polling attempts before giving up (default: 60)
21250
21457
  * @returns Stop function to cancel polling
21251
21458
  */
21252
- startPolling(checkWallet, onWalletReady, intervalMs = DEFAULT_INTERVAL_MS, maxAttempts = DEFAULT_MAX_ATTEMPTS) {
21459
+ startPolling(checkWallet, onWalletReady, intervalMs = DEFAULT_INTERVAL_MS, maxAttempts2 = DEFAULT_MAX_ATTEMPTS) {
21253
21460
  this.stop();
21254
21461
  this.attempts = 0;
21255
21462
  const poll = async () => {
21256
21463
  this.attempts++;
21257
- if (this.attempts > maxAttempts) {
21464
+ if (this.attempts > maxAttempts2) {
21258
21465
  this.stop();
21259
21466
  return;
21260
21467
  }
@@ -29073,13 +29280,13 @@ function createRemoteMemoryStore(options) {
29073
29280
  });
29074
29281
  return run;
29075
29282
  };
29076
- const live = async (id2) => {
29283
+ const live2 = async (id2) => {
29077
29284
  const record2 = await persistence.get(id2);
29078
29285
  return record2 && !record2.memory.is_deleted ? record2 : null;
29079
29286
  };
29080
29287
  const mutateLocked = async (id2, change, edit, writeOptions) => {
29081
29288
  writeOptions?.signal?.throwIfAborted();
29082
- const record2 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live(id2);
29289
+ const record2 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live2(id2);
29083
29290
  if (!record2) return null;
29084
29291
  if (record2.memory.is_deleted) return null;
29085
29292
  if (writeOptions?.canWrite && !await writeOptions.canWrite())
@@ -29877,7 +30084,7 @@ function createRemoteMemoryStore(options) {
29877
30084
  }, clear);
29878
30085
  return snapshot.then((topics) => structuredClone(topics));
29879
30086
  },
29880
- get: async (id2) => asStored(await live(id2)),
30087
+ get: async (id2) => asStored(await live2(id2)),
29881
30088
  listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
29882
30089
  (record2) => stored(record2.memory)
29883
30090
  ),
@@ -29962,7 +30169,7 @@ function createRemoteMemoryStore(options) {
29962
30169
  return serialized(
29963
30170
  first,
29964
30171
  () => serialized(second, async () => {
29965
- const [old, next] = await Promise.all([live(id2), live(supersededById)]);
30172
+ const [old, next] = await Promise.all([live2(id2), live2(supersededById)]);
29966
30173
  if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
29967
30174
  if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
29968
30175
  const saved = await persistence.putMany([
@@ -29983,7 +30190,7 @@ function createRemoteMemoryStore(options) {
29983
30190
  (memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
29984
30191
  ),
29985
30192
  restore: (id2) => serialized(id2, async () => {
29986
- const record2 = await live(id2);
30193
+ const record2 = await live2(id2);
29987
30194
  if (!record2) return false;
29988
30195
  if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
29989
30196
  return true;
@@ -40044,82 +40251,45 @@ function useChatStorage(options) {
40044
40251
  await inbox.putPublicKey(publicKey);
40045
40252
  registeredInboxKeyRef.current = { inbox, publicKey };
40046
40253
  }
40047
- const results = [];
40048
- for (const item of await inbox.list()) {
40049
- let opened;
40050
- try {
40051
- opened = await openInboxItem(item, keyPair);
40052
- } catch (err) {
40053
- results.push({
40054
- id: item.id,
40055
- conversationId: null,
40056
- status: "unreadable",
40057
- assistantMessage: null,
40058
- error: err instanceof Error ? err.message : String(err)
40254
+ return deliverInboxAnswers({
40255
+ inbox,
40256
+ keyPair,
40257
+ backend,
40258
+ store: async (opened, messageId) => {
40259
+ const { redactor } = resolveCallPii(
40260
+ void 0,
40261
+ piiRedaction,
40262
+ () => getConversationRedactor(opened.conversation_id, nerDetectorRef.current)
40263
+ );
40264
+ const knownToolCallEventIds = await backend.getToolCallEventIds(opened.conversation_id);
40265
+ const { fields, fileIds } = await toAssistantMessageFields(
40266
+ opened.response,
40267
+ opened.conversation_id,
40268
+ knownToolCallEventIds
40269
+ );
40270
+ const upserted = await backend.upsertMessage({
40271
+ ...fields,
40272
+ content: redactor ? redactor.deAnonymize(fields.content) : fields.content,
40273
+ thinking: redactor && fields.thinking ? redactor.deAnonymize(fields.thinking) : fields.thinking,
40274
+ conversationId: opened.conversation_id,
40275
+ role: "assistant",
40276
+ model: opened.model,
40277
+ parentMessageId: opened.parent_message_id ?? void 0,
40278
+ wasStopped: opened.status === "tool_request",
40279
+ uniqueId: messageId
40059
40280
  });
40060
- continue;
40061
- }
40062
- const base = { id: item.id, conversationId: opened.conversation_id };
40063
- try {
40064
- const messageId = opened.assistant_message_id ?? `msg_bg_${opened.inference_id}`;
40065
- const [existing] = await backend.getMessagesByIds([messageId]);
40066
- if (!existing) {
40067
- const parent = opened.parent_message_id;
40068
- const ownsTurn = parent ? (await backend.getMessagesByIds([parent])).length > 0 : await backend.getConversation(opened.conversation_id) !== null;
40069
- if (!ownsTurn) {
40070
- results.push({ ...base, status: "elsewhere", assistantMessage: null });
40071
- continue;
40072
- }
40073
- }
40074
- let stored2 = existing;
40075
- if (!stored2) {
40076
- const { redactor } = resolveCallPii(
40077
- void 0,
40078
- piiRedaction,
40079
- () => getConversationRedactor(opened.conversation_id, nerDetectorRef.current)
40080
- );
40081
- const knownToolCallEventIds = await backend.getToolCallEventIds(opened.conversation_id);
40082
- const { fields, fileIds } = await toAssistantMessageFields(
40083
- opened.response,
40084
- opened.conversation_id,
40085
- knownToolCallEventIds
40086
- );
40087
- stored2 = await backend.createMessage({
40088
- ...fields,
40089
- content: redactor ? redactor.deAnonymize(fields.content) : fields.content,
40090
- thinking: redactor && fields.thinking ? redactor.deAnonymize(fields.thinking) : fields.thinking,
40091
- conversationId: opened.conversation_id,
40092
- role: "assistant",
40093
- model: opened.model,
40094
- parentMessageId: opened.parent_message_id ?? void 0,
40095
- wasStopped: opened.status === "tool_request" ? true : void 0,
40096
- uniqueId: messageId
40097
- });
40098
- if (fileIds.length > 0) {
40099
- try {
40100
- await updateMediaMessageIdBatchOp(mediaCtx, fileIds, stored2.uniqueId);
40101
- } catch (err) {
40102
- getLogger().warn("[useChatStorage] Failed to link inbox media:", err);
40103
- }
40281
+ const stored2 = await clearTurnErrors(backend, upserted);
40282
+ if (fileIds.length > 0) {
40283
+ try {
40284
+ await updateMediaMessageIdBatchOp(mediaCtx, fileIds, stored2.uniqueId);
40285
+ } catch (err) {
40286
+ getLogger().warn("[useChatStorage] Failed to link inbox media:", err);
40104
40287
  }
40105
- void embedMessageAsync(stored2, (text16) => redactor ? redactor.maskText(text16) : text16);
40106
40288
  }
40107
- await inbox.remove(item.id);
40108
- results.push({
40109
- ...base,
40110
- status: existing ? "delivered" : "stored",
40111
- assistantMessage: stored2
40112
- });
40113
- } catch (err) {
40114
- results.push({
40115
- ...base,
40116
- status: "retry",
40117
- assistantMessage: null,
40118
- error: err instanceof Error ? err.message : String(err)
40119
- });
40289
+ void embedMessageAsync(stored2, (text16) => redactor ? redactor.maskText(text16) : text16);
40290
+ return stored2;
40120
40291
  }
40121
- }
40122
- return results;
40292
+ });
40123
40293
  }, [
40124
40294
  inbox,
40125
40295
  walletAddress,
@@ -41604,11 +41774,11 @@ function usePhoneCalls(options = {}) {
41604
41774
  pollRunIdRef.current = runId;
41605
41775
  setIsPolling(true);
41606
41776
  const intervalMs = pollOptions.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
41607
- const maxAttempts = pollOptions.maxAttempts ?? DEFAULT_POLL_MAX_ATTEMPTS;
41777
+ const maxAttempts2 = pollOptions.maxAttempts ?? DEFAULT_POLL_MAX_ATTEMPTS;
41608
41778
  const stopWhenCompleted = pollOptions.stopWhenCompleted ?? true;
41609
41779
  let latestCall = null;
41610
41780
  try {
41611
- for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
41781
+ for (let attempt = 0; attempt < maxAttempts2; attempt += 1) {
41612
41782
  if (pollRunIdRef.current !== runId) {
41613
41783
  break;
41614
41784
  }
@@ -41638,7 +41808,7 @@ function usePhoneCalls(options = {}) {
41638
41808
  break;
41639
41809
  }
41640
41810
  }
41641
- if (attempt < maxAttempts - 1) {
41811
+ if (attempt < maxAttempts2 - 1) {
41642
41812
  await wait2(intervalMs);
41643
41813
  }
41644
41814
  }
@@ -43153,6 +43323,7 @@ function useWalletBinding(options = {}) {
43153
43323
  }
43154
43324
  // Annotate the CommonJS export names for ESM import in node:
43155
43325
  0 && (module.exports = {
43326
+ ANUMA_CONVERSATION_ID,
43156
43327
  Anuma,
43157
43328
  AnumaJsxError,
43158
43329
  AnumaShadowIsolationProvider,
@@ -43257,6 +43428,8 @@ function useWalletBinding(options = {}) {
43257
43428
  WordProcessor,
43258
43429
  ZipProcessor,
43259
43430
  addConversationMemoriesOp,
43431
+ anumaLastReadSortKey,
43432
+ anumaTurnContent,
43260
43433
  appFileToStored,
43261
43434
  archiveVaultMemoryOp,
43262
43435
  assembleMemoryContext,
@@ -43296,6 +43469,7 @@ function useWalletBinding(options = {}) {
43296
43469
  consoleLogger,
43297
43470
  conversationMemoryToStored,
43298
43471
  cosineInt8,
43472
+ countUnreadAnumaTurns,
43299
43473
  createAutoExtractor,
43300
43474
  createChunkVectorCache,
43301
43475
  createCryptoPricePreProcessor,
@@ -43365,6 +43539,7 @@ function useWalletBinding(options = {}) {
43365
43539
  encryptDataBytes,
43366
43540
  encryptDataWithKey,
43367
43541
  encryptToolCallEventsOp,
43542
+ ensureAnumaConversation,
43368
43543
  ensureDefaultFoldersOp,
43369
43544
  expandToolSetsAdditive,
43370
43545
  exportElementToPdf,
@@ -43475,6 +43650,7 @@ function useWalletBinding(options = {}) {
43475
43650
  listActiveStreams,
43476
43651
  loadSettings,
43477
43652
  localChatBackend,
43653
+ markAnumaRead,
43478
43654
  maskScopedEmbeddingCache,
43479
43655
  maxVaultAttachmentBytes,
43480
43656
  mediaToStored,
@@ -43500,6 +43676,7 @@ function useWalletBinding(options = {}) {
43500
43676
  quantizeEmbedding,
43501
43677
  queueManager,
43502
43678
  rankProfileCandidates,
43679
+ readAnumaTurn,
43503
43680
  readEncryptedFile,
43504
43681
  recall,
43505
43682
  reencryptMemoryField,