@anuma/sdk 7.3.0 → 7.3.2

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.
@@ -15181,7 +15181,7 @@ function onKeyAvailable(address, callback) {
15181
15181
  callbacks.add(callback);
15182
15182
  return () => {
15183
15183
  callbacks.delete(callback);
15184
- if (callbacks.size === 0) {
15184
+ if (callbacks.size === 0 && keyAvailableCallbacks.get(address) === callbacks) {
15185
15185
  keyAvailableCallbacks.delete(address);
15186
15186
  }
15187
15187
  };
@@ -26093,6 +26093,67 @@ var import_watermelondb19 = __toESM(require_watermelondb());
26093
26093
  // src/lib/db/entities/operations.ts
26094
26094
  var import_watermelondb18 = __toESM(require_watermelondb());
26095
26095
 
26096
+ // src/lib/db/memoryVault/types.ts
26097
+ var MEMORY_KINDS = [
26098
+ "display_name",
26099
+ "birth_date",
26100
+ "bio",
26101
+ "occupation",
26102
+ "interest",
26103
+ "gender",
26104
+ "height_cm",
26105
+ "looking_for",
26106
+ "politics",
26107
+ "religion",
26108
+ "ethnicity",
26109
+ "smoking",
26110
+ "drinking",
26111
+ "exercise",
26112
+ "sexuality",
26113
+ "prompt"
26114
+ ];
26115
+ var MEMORY_LEVELS = ["private", "matching", "profile"];
26116
+ var MemoryLevelError = class extends Error {
26117
+ constructor(message) {
26118
+ super(message);
26119
+ this.name = "MemoryLevelError";
26120
+ }
26121
+ };
26122
+ var MemorySourceIneligibleError = class extends Error {
26123
+ constructor() {
26124
+ super("Memory source is no longer eligible");
26125
+ this.name = "MemorySourceIneligibleError";
26126
+ }
26127
+ };
26128
+ var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
26129
+ function levelFromScope(scope) {
26130
+ return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
26131
+ }
26132
+ function scopeForLevel(level) {
26133
+ return level === "private" ? "private" : "shared";
26134
+ }
26135
+ function resolveMemoryLevel(level, scope) {
26136
+ return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
26137
+ }
26138
+ function levelForScopeChange(current, nextScope) {
26139
+ const implied = levelFromScope(nextScope);
26140
+ return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
26141
+ }
26142
+ function parseMedia(value) {
26143
+ if (typeof value !== "string" || value === "") return null;
26144
+ try {
26145
+ const parsed = JSON.parse(value);
26146
+ if (!Array.isArray(parsed)) return null;
26147
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
26148
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
26149
+ objectKey: r.objectKey ?? r.object_key ?? null
26150
+ })).filter((r) => Number.isFinite(r.feedItemId));
26151
+ return refs.length > 0 ? refs : null;
26152
+ } catch {
26153
+ return null;
26154
+ }
26155
+ }
26156
+
26096
26157
  // src/lib/db/entities/types.ts
26097
26158
  var ENTITY_KINDS = [
26098
26159
  "person",
@@ -26142,7 +26203,7 @@ function parseTopics(value) {
26142
26203
  // src/lib/db/entities/operations.ts
26143
26204
  async function assertCanWrite(ctx) {
26144
26205
  if (ctx.canWrite && !await ctx.canWrite()) {
26145
- throw new Error("Memory source is no longer eligible");
26206
+ throw new MemorySourceIneligibleError();
26146
26207
  }
26147
26208
  }
26148
26209
  function entityToStored(e) {
@@ -26534,61 +26595,6 @@ function serializeSourceChunkIds(ids) {
26534
26595
  return JSON.stringify(ids.slice(start));
26535
26596
  }
26536
26597
 
26537
- // src/lib/db/memoryVault/types.ts
26538
- var MEMORY_KINDS = [
26539
- "display_name",
26540
- "birth_date",
26541
- "bio",
26542
- "occupation",
26543
- "interest",
26544
- "gender",
26545
- "height_cm",
26546
- "looking_for",
26547
- "politics",
26548
- "religion",
26549
- "ethnicity",
26550
- "smoking",
26551
- "drinking",
26552
- "exercise",
26553
- "sexuality",
26554
- "prompt"
26555
- ];
26556
- var MEMORY_LEVELS = ["private", "matching", "profile"];
26557
- var MemoryLevelError = class extends Error {
26558
- constructor(message) {
26559
- super(message);
26560
- this.name = "MemoryLevelError";
26561
- }
26562
- };
26563
- var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
26564
- function levelFromScope(scope) {
26565
- return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
26566
- }
26567
- function scopeForLevel(level) {
26568
- return level === "private" ? "private" : "shared";
26569
- }
26570
- function resolveMemoryLevel(level, scope) {
26571
- return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
26572
- }
26573
- function levelForScopeChange(current, nextScope) {
26574
- const implied = levelFromScope(nextScope);
26575
- return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
26576
- }
26577
- function parseMedia(value) {
26578
- if (typeof value !== "string" || value === "") return null;
26579
- try {
26580
- const parsed = JSON.parse(value);
26581
- if (!Array.isArray(parsed)) return null;
26582
- const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
26583
- feedItemId: Number(r.feedItemId ?? r.feed_item_id),
26584
- objectKey: r.objectKey ?? r.object_key ?? null
26585
- })).filter((r) => Number.isFinite(r.feedItemId));
26586
- return refs.length > 0 ? refs : null;
26587
- } catch {
26588
- return null;
26589
- }
26590
- }
26591
-
26592
26598
  // src/lib/db/memoryVault/operations.ts
26593
26599
  function visibilityOrPrivate(value) {
26594
26600
  return value === "public" ? value : "private";
@@ -26608,7 +26614,7 @@ function isKinded(record) {
26608
26614
  }
26609
26615
  async function assertCanWrite2(ctx) {
26610
26616
  if (ctx.canWrite && !await ctx.canWrite()) {
26611
- throw new Error("Memory source is no longer eligible");
26617
+ throw new MemorySourceIneligibleError();
26612
26618
  }
26613
26619
  }
26614
26620
  function assertValidKindLevel(kind, level) {
@@ -27285,7 +27291,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
27285
27291
  ctx.embeddedWalletSigner
27286
27292
  );
27287
27293
  } catch (err) {
27288
- if (err instanceof MemoryLevelError) throw err;
27294
+ if (err instanceof MemoryLevelError || err instanceof MemorySourceIneligibleError) throw err;
27289
27295
  return null;
27290
27296
  }
27291
27297
  }
@@ -30961,6 +30967,13 @@ var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
30961
30967
  var DEFAULT_SCOPE = "private";
30962
30968
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
30963
30969
  var DEFAULT_CONSOLIDATE_TOP_K = 20;
30970
+ var RetainError = class extends Error {
30971
+ constructor(reason, message) {
30972
+ super(message);
30973
+ this.reason = reason;
30974
+ this.name = "RetainError";
30975
+ }
30976
+ };
30964
30977
  async function retain(content, ctx, options = {}) {
30965
30978
  const embeddingOptions = {
30966
30979
  ...ctx.embeddingOptions,
@@ -31016,7 +31029,8 @@ async function retainWithPersistence(content, ctx, options = {}) {
31016
31029
  });
31017
31030
  prepared = withoutKindedRows(prepared);
31018
31031
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
31019
- throw new Error(
31032
+ throw new RetainError(
31033
+ "embeddings-unavailable",
31020
31034
  "retain: embeddings unavailable \u2014 refusing to auto-merge against an inert cosine lane, which would create a duplicate instead of merging into the existing memory. Retry when embeddings recover, or pass enableAutoMerge: false to force a create."
31021
31035
  );
31022
31036
  }
@@ -31386,7 +31400,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31386
31400
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
31387
31401
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
31388
31402
  if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
31389
- throw new Error(`retain: merge into memory ${targetId} failed to persist`);
31403
+ throw new RetainError(
31404
+ "merge-not-persisted",
31405
+ `retain: merge into memory ${targetId} failed to persist`
31406
+ );
31390
31407
  }
31391
31408
  }
31392
31409
 
@@ -31544,6 +31561,12 @@ function restoreCandidates(candidates, redactor, ownNames) {
31544
31561
  (c) => c.candidate.content.length <= MAX_CONTENT_LENGTH && !c.unresolved && !isLowSignalContent(c.candidate.content, ownNames)
31545
31562
  ).map((c) => c.candidate);
31546
31563
  }
31564
+ function writeFailureReasonOf(err) {
31565
+ if (err instanceof MemorySourceIneligibleError) return "source-ineligible";
31566
+ if (err instanceof RetainError) return err.reason;
31567
+ if (err?.name === "AbortError") return "aborted";
31568
+ return "unknown";
31569
+ }
31547
31570
  async function extractAndRetain(messages, retainCtx, options) {
31548
31571
  const { memoryStore, signal } = options;
31549
31572
  if (memoryStore === null) throw new Error("Memory store is not ready");
@@ -31633,6 +31656,7 @@ async function extractAndRetain(messages, retainCtx, options) {
31633
31656
  const results = [];
31634
31657
  const quarantinedInfo = [];
31635
31658
  let failedWrites = 0;
31659
+ let writeFailureReason;
31636
31660
  let auditRows;
31637
31661
  const tRetain = Date.now();
31638
31662
  for (const { candidate, isQuarantined, reason, signature } of toRetain) {
@@ -31728,6 +31752,7 @@ async function extractAndRetain(messages, retainCtx, options) {
31728
31752
  }
31729
31753
  } catch (err) {
31730
31754
  failedWrites++;
31755
+ writeFailureReason ?? (writeFailureReason = writeFailureReasonOf(err));
31731
31756
  log.warn("[memory/extract] retain failed for one candidate", err);
31732
31757
  options.onCandidateFailed?.(candidate, err);
31733
31758
  }
@@ -31740,6 +31765,7 @@ async function extractAndRetain(messages, retainCtx, options) {
31740
31765
  candidates: succeededCandidates,
31741
31766
  results,
31742
31767
  failedCount: failedWrites,
31768
+ ...writeFailureReason !== void 0 && { writeFailureReason },
31743
31769
  outcome,
31744
31770
  quarantined: quarantinedInfo,
31745
31771
  funnel: {
@@ -32008,7 +32034,17 @@ function createAutoExtractor(options) {
32008
32034
  const t0 = Date.now();
32009
32035
  void (async () => {
32010
32036
  try {
32011
- const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
32037
+ const {
32038
+ candidates,
32039
+ results,
32040
+ failedCount,
32041
+ writeFailureReason,
32042
+ outcome,
32043
+ failure,
32044
+ funnel,
32045
+ timings,
32046
+ model
32047
+ } = await extractAndRetain(window2, retainCtx, {
32012
32048
  extract,
32013
32049
  memoryStore: options.memoryStore,
32014
32050
  signal: options.signal,
@@ -32044,6 +32080,7 @@ function createAutoExtractor(options) {
32044
32080
  candidates,
32045
32081
  results,
32046
32082
  failedCount,
32083
+ ...writeFailureReason !== void 0 && { writeFailureReason },
32047
32084
  durationMs: Date.now() - t0,
32048
32085
  conversationId,
32049
32086
  outcome,
@@ -34156,10 +34193,10 @@ function createLocalMemoryStore(options) {
34156
34193
  const assertWrite = async (writeOptions) => {
34157
34194
  writeOptions?.signal?.throwIfAborted();
34158
34195
  if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
34159
- throw new Error("Memory source is no longer eligible");
34196
+ throw new MemorySourceIneligibleError();
34160
34197
  }
34161
34198
  if (options.canWrite && !await options.canWrite()) {
34162
- throw new Error("Memory source is no longer eligible");
34199
+ throw new MemorySourceIneligibleError();
34163
34200
  }
34164
34201
  writeOptions?.signal?.throwIfAborted();
34165
34202
  };
@@ -35114,10 +35151,20 @@ function batchError(result) {
35114
35151
  var AccountFailureError = class extends Error {
35115
35152
  };
35116
35153
  var LockedSourcesError = class extends Error {
35117
- constructor(persistentIds) {
35118
- super("Source messages are locked; retained for retry");
35154
+ constructor(persistentIds, locked) {
35155
+ const counts = /* @__PURE__ */ new Map();
35156
+ for (const message of locked) {
35157
+ const version = /^enc:(v\d+):/.exec(message.content)?.[1] ?? "unknown";
35158
+ const key = `${message.decryptionStatus ?? "no_status"}:${version}`;
35159
+ counts.set(key, (counts.get(key) ?? 0) + 1);
35160
+ }
35161
+ const summary = [...counts].map(([key, count]) => `${key}=${count}`).join(", ");
35162
+ super(`Source messages are locked; retained for retry (${summary})`);
35119
35163
  this.persistentIds = persistentIds;
35120
35164
  }
35165
+ get awaitingKey() {
35166
+ return this.persistentIds.length === 0;
35167
+ }
35121
35168
  };
35122
35169
  function splitTurns(messages) {
35123
35170
  const turns = [];
@@ -35171,6 +35218,8 @@ function createDurableAutoExtractor(options) {
35171
35218
  const attempts = /* @__PURE__ */ new Map();
35172
35219
  const sessionFailures = /* @__PURE__ */ new Map();
35173
35220
  const skippedThisSession = /* @__PURE__ */ new Set();
35221
+ const awaitingKey = /* @__PURE__ */ new Set();
35222
+ let keyEpoch = 0;
35174
35223
  const clock = options.now ?? Date.now;
35175
35224
  const reportError = (error, conversationId) => {
35176
35225
  try {
@@ -35364,13 +35413,15 @@ function createDurableAutoExtractor(options) {
35364
35413
  for (const job of pending) {
35365
35414
  if (disposed) break;
35366
35415
  const attempted = attempts.get(job.id) ?? 0;
35367
- if (attempted >= MAX_ATTEMPTS || skippedThisSession.has(job.id)) continue;
35416
+ if (attempted >= MAX_ATTEMPTS || skippedThisSession.has(job.id) || awaitingKey.has(job.id))
35417
+ continue;
35368
35418
  if (processed >= MAX_JOBS_PER_PASS) {
35369
35419
  scheduleAfterSuccess = true;
35370
35420
  break;
35371
35421
  }
35372
35422
  processed++;
35373
35423
  const conversationId = String(job._getRaw("conversation_id"));
35424
+ const epochAtRead = keyEpoch;
35374
35425
  let ids = [];
35375
35426
  let loaded = [];
35376
35427
  try {
@@ -35404,16 +35455,39 @@ function createDurableAutoExtractor(options) {
35404
35455
  );
35405
35456
  continue;
35406
35457
  }
35407
- const locked = loaded.filter((message) => message && isEncrypted(message.content));
35458
+ const foreign = new Set(
35459
+ ids.filter((_id, index) => loaded[index]?.conversationId !== conversationId)
35460
+ );
35461
+ if (foreign.size) {
35462
+ await database.write(
35463
+ () => job.update(
35464
+ (r) => r._setRaw(
35465
+ "message_ids",
35466
+ JSON.stringify(idsOf(job).filter((id) => !foreign.has(id)))
35467
+ )
35468
+ )
35469
+ );
35470
+ attempts.delete(job.id);
35471
+ scheduleAfterSuccess = true;
35472
+ reportError(
35473
+ new Error(`Dropped ${foreign.size} source id(s) from another conversation`),
35474
+ conversationId
35475
+ );
35476
+ continue;
35477
+ }
35478
+ const locked = loaded.filter(
35479
+ (message) => !!message && isEncrypted(message.content)
35480
+ );
35408
35481
  if (locked.length) {
35409
35482
  throw new LockedSourcesError(
35410
35483
  locked.flatMap(
35411
35484
  (message) => message.decryptionStatus === "auth_mismatch" || message.decryptionStatus === "invalid_payload" ? [message.uniqueId] : []
35412
- )
35485
+ ),
35486
+ locked
35413
35487
  );
35414
35488
  }
35415
35489
  const messages = loaded.flatMap(
35416
- (m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
35490
+ (m) => m && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
35417
35491
  );
35418
35492
  const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
35419
35493
  const jobFolderId = job._getRaw("folder_id") ?? null;
@@ -35463,6 +35537,12 @@ function createDurableAutoExtractor(options) {
35463
35537
  scheduleAfterSuccess = true;
35464
35538
  } catch (error) {
35465
35539
  if (disposed) break;
35540
+ if (error instanceof LockedSourcesError && error.awaitingKey) {
35541
+ reportError(error, conversationId);
35542
+ if (keyEpoch === epochAtRead) awaitingKey.add(job.id);
35543
+ else scheduleAfterSuccess = true;
35544
+ continue;
35545
+ }
35466
35546
  attempts.set(job.id, attempted + 1);
35467
35547
  retry = true;
35468
35548
  reportError(error, conversationId);
@@ -35490,7 +35570,18 @@ function createDurableAutoExtractor(options) {
35490
35570
  activeBatch?.abort(options.signal?.reason);
35491
35571
  if (timer !== void 0) clearTimeout(timer);
35492
35572
  options.signal?.removeEventListener("abort", dispose);
35573
+ unsubscribeKey?.();
35493
35574
  }
35575
+ const unsubscribeKey = vault.walletAddress ? onKeyAvailable(vault.walletAddress, () => {
35576
+ keyEpoch++;
35577
+ if (!awaitingKey.size) return;
35578
+ awaitingKey.clear();
35579
+ if (timer !== void 0) {
35580
+ clearTimeout(timer);
35581
+ timer = void 0;
35582
+ }
35583
+ schedule(0);
35584
+ }) : void 0;
35494
35585
  if (options.signal?.aborted) dispose();
35495
35586
  else options.signal?.addEventListener("abort", dispose, { once: true });
35496
35587
  schedule(0);
@@ -35506,9 +35597,31 @@ function createDurableAutoExtractor(options) {
35506
35597
  (candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
35507
35598
  );
35508
35599
  const positions = new Map(ids.map((id, index) => [id, index]));
35600
+ const watermarks = existing.flatMap((prior) => {
35601
+ const watermark = prior._getRaw("watermark");
35602
+ return typeof watermark === "string" && watermark ? [watermark] : [];
35603
+ });
35604
+ if (watermarks.length) {
35605
+ const misplaced = new Set(
35606
+ await storage.messagesCollection.query(
35607
+ import_watermelondb25.Q.where("id", import_watermelondb25.Q.oneOf(watermarks)),
35608
+ import_watermelondb25.Q.where("conversation_id", import_watermelondb25.Q.notEq(conversationId))
35609
+ ).fetchIds()
35610
+ );
35611
+ for (const prior of existing)
35612
+ if (misplaced.has(String(prior._getRaw("watermark"))))
35613
+ await prior.update((r) => {
35614
+ r._setRaw("watermark", null);
35615
+ r._setRaw("watermark_seq", null);
35616
+ });
35617
+ }
35509
35618
  const rows = await storage.messagesCollection.query(import_watermelondb25.Q.where("id", import_watermelondb25.Q.oneOf(ids))).fetch();
35619
+ const foreignRows = new Set(
35620
+ rows.filter((row) => row._getRaw("conversation_id") !== conversationId).map((row) => row.id)
35621
+ );
35510
35622
  const sequences = /* @__PURE__ */ new Map();
35511
35623
  for (const row of rows) {
35624
+ if (foreignRows.has(row.id)) continue;
35512
35625
  const sequence = Number(row._getRaw("message_id"));
35513
35626
  if (Number.isFinite(sequence) && sequence > 0) sequences.set(row.id, sequence);
35514
35627
  }
@@ -35551,13 +35664,14 @@ function createDurableAutoExtractor(options) {
35551
35664
  const ownWatermark = job?._getRaw("watermark");
35552
35665
  const atOwnWatermark = !!job && boundary >= 0 && failedSessionsOf(job, String(ownWatermark)) < MAX_FAILED_SESSIONS && (ids[boundary] === ownWatermark || sequences.get(ids[boundary]) !== void 0 && sequences.get(ids[boundary]) === seqOf(job));
35553
35666
  const overlapStart = atOwnWatermark ? Math.max(0, boundary - 1) : start;
35554
- const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id));
35667
+ const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id) && !foreignRows.has(id));
35555
35668
  if (!fresh.length) return;
35556
35669
  if (job) {
35557
35670
  await job.update(
35558
35671
  (r) => r._setRaw("message_ids", JSON.stringify([.../* @__PURE__ */ new Set([...idsOf(job), ...fresh])]))
35559
35672
  );
35560
35673
  attempts.delete(job.id);
35674
+ awaitingKey.delete(job.id);
35561
35675
  } else {
35562
35676
  await jobs.create((r) => {
35563
35677
  r._setRaw("owner_key", owner);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "7.3.0",
3
+ "version": "7.3.2",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",