@anuma/sdk 7.3.0 → 7.3.1

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.
@@ -11131,9 +11131,72 @@ import { Q as Q5 } from "@nozbe/watermelondb";
11131
11131
 
11132
11132
  // src/lib/db/entities/operations.ts
11133
11133
  import { Q as Q4 } from "@nozbe/watermelondb";
11134
+
11135
+ // src/lib/db/memoryVault/types.ts
11136
+ var MEMORY_KINDS = [
11137
+ "display_name",
11138
+ "birth_date",
11139
+ "bio",
11140
+ "occupation",
11141
+ "interest",
11142
+ "gender",
11143
+ "height_cm",
11144
+ "looking_for",
11145
+ "politics",
11146
+ "religion",
11147
+ "ethnicity",
11148
+ "smoking",
11149
+ "drinking",
11150
+ "exercise",
11151
+ "sexuality",
11152
+ "prompt"
11153
+ ];
11154
+ var MEMORY_LEVELS = ["private", "matching", "profile"];
11155
+ var MemoryLevelError = class extends Error {
11156
+ constructor(message) {
11157
+ super(message);
11158
+ this.name = "MemoryLevelError";
11159
+ }
11160
+ };
11161
+ var MemorySourceIneligibleError = class extends Error {
11162
+ constructor() {
11163
+ super("Memory source is no longer eligible");
11164
+ this.name = "MemorySourceIneligibleError";
11165
+ }
11166
+ };
11167
+ var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
11168
+ function levelFromScope(scope) {
11169
+ return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
11170
+ }
11171
+ function scopeForLevel(level) {
11172
+ return level === "private" ? "private" : "shared";
11173
+ }
11174
+ function resolveMemoryLevel(level, scope) {
11175
+ return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
11176
+ }
11177
+ function levelForScopeChange(current, nextScope) {
11178
+ const implied = levelFromScope(nextScope);
11179
+ return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
11180
+ }
11181
+ function parseMedia(value) {
11182
+ if (typeof value !== "string" || value === "") return null;
11183
+ try {
11184
+ const parsed = JSON.parse(value);
11185
+ if (!Array.isArray(parsed)) return null;
11186
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
11187
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
11188
+ objectKey: r.objectKey ?? r.object_key ?? null
11189
+ })).filter((r) => Number.isFinite(r.feedItemId));
11190
+ return refs.length > 0 ? refs : null;
11191
+ } catch {
11192
+ return null;
11193
+ }
11194
+ }
11195
+
11196
+ // src/lib/db/entities/operations.ts
11134
11197
  async function assertCanWrite(ctx) {
11135
11198
  if (ctx.canWrite && !await ctx.canWrite()) {
11136
- throw new Error("Memory source is no longer eligible");
11199
+ throw new MemorySourceIneligibleError();
11137
11200
  }
11138
11201
  }
11139
11202
  function entityToStored(e) {
@@ -11525,61 +11588,6 @@ function serializeSourceChunkIds(ids) {
11525
11588
  return JSON.stringify(ids.slice(start));
11526
11589
  }
11527
11590
 
11528
- // src/lib/db/memoryVault/types.ts
11529
- var MEMORY_KINDS = [
11530
- "display_name",
11531
- "birth_date",
11532
- "bio",
11533
- "occupation",
11534
- "interest",
11535
- "gender",
11536
- "height_cm",
11537
- "looking_for",
11538
- "politics",
11539
- "religion",
11540
- "ethnicity",
11541
- "smoking",
11542
- "drinking",
11543
- "exercise",
11544
- "sexuality",
11545
- "prompt"
11546
- ];
11547
- var MEMORY_LEVELS = ["private", "matching", "profile"];
11548
- var MemoryLevelError = class extends Error {
11549
- constructor(message) {
11550
- super(message);
11551
- this.name = "MemoryLevelError";
11552
- }
11553
- };
11554
- var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
11555
- function levelFromScope(scope) {
11556
- return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
11557
- }
11558
- function scopeForLevel(level) {
11559
- return level === "private" ? "private" : "shared";
11560
- }
11561
- function resolveMemoryLevel(level, scope) {
11562
- return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
11563
- }
11564
- function levelForScopeChange(current, nextScope) {
11565
- const implied = levelFromScope(nextScope);
11566
- return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
11567
- }
11568
- function parseMedia(value) {
11569
- if (typeof value !== "string" || value === "") return null;
11570
- try {
11571
- const parsed = JSON.parse(value);
11572
- if (!Array.isArray(parsed)) return null;
11573
- const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
11574
- feedItemId: Number(r.feedItemId ?? r.feed_item_id),
11575
- objectKey: r.objectKey ?? r.object_key ?? null
11576
- })).filter((r) => Number.isFinite(r.feedItemId));
11577
- return refs.length > 0 ? refs : null;
11578
- } catch {
11579
- return null;
11580
- }
11581
- }
11582
-
11583
11591
  // src/lib/db/memoryVault/operations.ts
11584
11592
  function visibilityOrPrivate(value) {
11585
11593
  return value === "public" ? value : "private";
@@ -11599,7 +11607,7 @@ function isKinded(record2) {
11599
11607
  }
11600
11608
  async function assertCanWrite2(ctx) {
11601
11609
  if (ctx.canWrite && !await ctx.canWrite()) {
11602
- throw new Error("Memory source is no longer eligible");
11610
+ throw new MemorySourceIneligibleError();
11603
11611
  }
11604
11612
  }
11605
11613
  function assertValidKindLevel(kind, level) {
@@ -12290,7 +12298,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
12290
12298
  ctx.embeddedWalletSigner
12291
12299
  );
12292
12300
  } catch (err) {
12293
- if (err instanceof MemoryLevelError) throw err;
12301
+ if (err instanceof MemoryLevelError || err instanceof MemorySourceIneligibleError) throw err;
12294
12302
  return null;
12295
12303
  }
12296
12304
  }
@@ -15807,6 +15815,13 @@ var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
15807
15815
  var DEFAULT_SCOPE = "private";
15808
15816
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
15809
15817
  var DEFAULT_CONSOLIDATE_TOP_K = 20;
15818
+ var RetainError = class extends Error {
15819
+ constructor(reason, message) {
15820
+ super(message);
15821
+ this.reason = reason;
15822
+ this.name = "RetainError";
15823
+ }
15824
+ };
15810
15825
  async function retain(content, ctx, options = {}) {
15811
15826
  const embeddingOptions = {
15812
15827
  ...ctx.embeddingOptions,
@@ -15862,7 +15877,8 @@ async function retainWithPersistence(content, ctx, options = {}) {
15862
15877
  });
15863
15878
  prepared = withoutKindedRows(prepared);
15864
15879
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
15865
- throw new Error(
15880
+ throw new RetainError(
15881
+ "embeddings-unavailable",
15866
15882
  "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."
15867
15883
  );
15868
15884
  }
@@ -16232,7 +16248,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16232
16248
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
16233
16249
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
16234
16250
  if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
16235
- throw new Error(`retain: merge into memory ${targetId} failed to persist`);
16251
+ throw new RetainError(
16252
+ "merge-not-persisted",
16253
+ `retain: merge into memory ${targetId} failed to persist`
16254
+ );
16236
16255
  }
16237
16256
  }
16238
16257
 
@@ -16390,6 +16409,12 @@ function restoreCandidates(candidates, redactor, ownNames) {
16390
16409
  (c) => c.candidate.content.length <= MAX_CONTENT_LENGTH && !c.unresolved && !isLowSignalContent(c.candidate.content, ownNames)
16391
16410
  ).map((c) => c.candidate);
16392
16411
  }
16412
+ function writeFailureReasonOf(err) {
16413
+ if (err instanceof MemorySourceIneligibleError) return "source-ineligible";
16414
+ if (err instanceof RetainError) return err.reason;
16415
+ if (err?.name === "AbortError") return "aborted";
16416
+ return "unknown";
16417
+ }
16393
16418
  async function extractAndRetain(messages, retainCtx, options) {
16394
16419
  const { memoryStore, signal } = options;
16395
16420
  if (memoryStore === null) throw new Error("Memory store is not ready");
@@ -16479,6 +16504,7 @@ async function extractAndRetain(messages, retainCtx, options) {
16479
16504
  const results = [];
16480
16505
  const quarantinedInfo = [];
16481
16506
  let failedWrites = 0;
16507
+ let writeFailureReason;
16482
16508
  let auditRows;
16483
16509
  const tRetain = Date.now();
16484
16510
  for (const { candidate, isQuarantined, reason, signature } of toRetain) {
@@ -16574,6 +16600,7 @@ async function extractAndRetain(messages, retainCtx, options) {
16574
16600
  }
16575
16601
  } catch (err) {
16576
16602
  failedWrites++;
16603
+ writeFailureReason ?? (writeFailureReason = writeFailureReasonOf(err));
16577
16604
  log.warn("[memory/extract] retain failed for one candidate", err);
16578
16605
  options.onCandidateFailed?.(candidate, err);
16579
16606
  }
@@ -16586,6 +16613,7 @@ async function extractAndRetain(messages, retainCtx, options) {
16586
16613
  candidates: succeededCandidates,
16587
16614
  results,
16588
16615
  failedCount: failedWrites,
16616
+ ...writeFailureReason !== void 0 && { writeFailureReason },
16589
16617
  outcome: outcome2,
16590
16618
  quarantined: quarantinedInfo,
16591
16619
  funnel: {
@@ -16854,7 +16882,17 @@ function createAutoExtractor(options) {
16854
16882
  const t0 = Date.now();
16855
16883
  void (async () => {
16856
16884
  try {
16857
- const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
16885
+ const {
16886
+ candidates,
16887
+ results,
16888
+ failedCount,
16889
+ writeFailureReason,
16890
+ outcome: outcome2,
16891
+ failure,
16892
+ funnel,
16893
+ timings,
16894
+ model
16895
+ } = await extractAndRetain(window2, retainCtx, {
16858
16896
  extract,
16859
16897
  memoryStore: options.memoryStore,
16860
16898
  signal: options.signal,
@@ -16890,6 +16928,7 @@ function createAutoExtractor(options) {
16890
16928
  candidates,
16891
16929
  results,
16892
16930
  failedCount,
16931
+ ...writeFailureReason !== void 0 && { writeFailureReason },
16893
16932
  durationMs: Date.now() - t0,
16894
16933
  conversationId,
16895
16934
  outcome: outcome2,
@@ -18976,10 +19015,10 @@ function createLocalMemoryStore(options) {
18976
19015
  const assertWrite = async (writeOptions) => {
18977
19016
  writeOptions?.signal?.throwIfAborted();
18978
19017
  if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
18979
- throw new Error("Memory source is no longer eligible");
19018
+ throw new MemorySourceIneligibleError();
18980
19019
  }
18981
19020
  if (options.canWrite && !await options.canWrite()) {
18982
- throw new Error("Memory source is no longer eligible");
19021
+ throw new MemorySourceIneligibleError();
18983
19022
  }
18984
19023
  writeOptions?.signal?.throwIfAborted();
18985
19024
  };
@@ -19788,7 +19827,7 @@ function createRemoteMemoryPipeline(options) {
19788
19827
  const assertWrite = async () => {
19789
19828
  signal?.throwIfAborted();
19790
19829
  if (writeOptions?.canWrite && !await writeOptions.canWrite())
19791
- throw new Error("Memory source is no longer eligible");
19830
+ throw new MemorySourceIneligibleError();
19792
19831
  signal?.throwIfAborted();
19793
19832
  };
19794
19833
  const rejectUndecryptable = (failed) => {
@@ -20794,7 +20833,7 @@ function createRemoteMemoryStore(options) {
20794
20833
  if (!record2) return null;
20795
20834
  if (record2.memory.is_deleted) return null;
20796
20835
  if (writeOptions?.canWrite && !await writeOptions.canWrite())
20797
- throw new Error("Memory source is no longer eligible");
20836
+ throw new MemorySourceIneligibleError();
20798
20837
  writeOptions?.signal?.throwIfAborted();
20799
20838
  const next = edit(structuredClone(record2.memory));
20800
20839
  if (!next) return null;
@@ -22422,6 +22461,26 @@ function createDurableAutoExtractor(options) {
22422
22461
  );
22423
22462
  continue;
22424
22463
  }
22464
+ const foreign = new Set(
22465
+ ids.filter((_id, index) => loaded[index]?.conversationId !== conversationId)
22466
+ );
22467
+ if (foreign.size) {
22468
+ await database.write(
22469
+ () => job.update(
22470
+ (r) => r._setRaw(
22471
+ "message_ids",
22472
+ JSON.stringify(idsOf(job).filter((id) => !foreign.has(id)))
22473
+ )
22474
+ )
22475
+ );
22476
+ attempts.delete(job.id);
22477
+ scheduleAfterSuccess = true;
22478
+ reportError(
22479
+ new Error(`Dropped ${foreign.size} source id(s) from another conversation`),
22480
+ conversationId
22481
+ );
22482
+ continue;
22483
+ }
22425
22484
  const locked = loaded.filter((message) => message && isEncrypted(message.content));
22426
22485
  if (locked.length) {
22427
22486
  throw new LockedSourcesError(
@@ -22431,7 +22490,7 @@ function createDurableAutoExtractor(options) {
22431
22490
  );
22432
22491
  }
22433
22492
  const messages = loaded.flatMap(
22434
- (m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
22493
+ (m) => m && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
22435
22494
  );
22436
22495
  const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
22437
22496
  const jobFolderId = job._getRaw("folder_id") ?? null;
@@ -22524,9 +22583,31 @@ function createDurableAutoExtractor(options) {
22524
22583
  (candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
22525
22584
  );
22526
22585
  const positions = new Map(ids.map((id, index) => [id, index]));
22586
+ const watermarks = existing.flatMap((prior) => {
22587
+ const watermark = prior._getRaw("watermark");
22588
+ return typeof watermark === "string" && watermark ? [watermark] : [];
22589
+ });
22590
+ if (watermarks.length) {
22591
+ const misplaced = new Set(
22592
+ await storage.messagesCollection.query(
22593
+ Q9.where("id", Q9.oneOf(watermarks)),
22594
+ Q9.where("conversation_id", Q9.notEq(conversationId))
22595
+ ).fetchIds()
22596
+ );
22597
+ for (const prior of existing)
22598
+ if (misplaced.has(String(prior._getRaw("watermark"))))
22599
+ await prior.update((r) => {
22600
+ r._setRaw("watermark", null);
22601
+ r._setRaw("watermark_seq", null);
22602
+ });
22603
+ }
22527
22604
  const rows = await storage.messagesCollection.query(Q9.where("id", Q9.oneOf(ids))).fetch();
22605
+ const foreignRows = new Set(
22606
+ rows.filter((row) => row._getRaw("conversation_id") !== conversationId).map((row) => row.id)
22607
+ );
22528
22608
  const sequences = /* @__PURE__ */ new Map();
22529
22609
  for (const row of rows) {
22610
+ if (foreignRows.has(row.id)) continue;
22530
22611
  const sequence = Number(row._getRaw("message_id"));
22531
22612
  if (Number.isFinite(sequence) && sequence > 0) sequences.set(row.id, sequence);
22532
22613
  }
@@ -22569,7 +22650,7 @@ function createDurableAutoExtractor(options) {
22569
22650
  const ownWatermark = job?._getRaw("watermark");
22570
22651
  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));
22571
22652
  const overlapStart = atOwnWatermark ? Math.max(0, boundary - 1) : start;
22572
- const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id));
22653
+ const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id) && !foreignRows.has(id));
22573
22654
  if (!fresh.length) return;
22574
22655
  if (job) {
22575
22656
  await job.update(