@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.
@@ -10438,6 +10438,67 @@ __decorateClass([
10438
10438
  // src/lib/db/entities/operations.ts
10439
10439
  import { Q as Q5 } from "@nozbe/watermelondb";
10440
10440
 
10441
+ // src/lib/db/memoryVault/types.ts
10442
+ var MEMORY_KINDS = [
10443
+ "display_name",
10444
+ "birth_date",
10445
+ "bio",
10446
+ "occupation",
10447
+ "interest",
10448
+ "gender",
10449
+ "height_cm",
10450
+ "looking_for",
10451
+ "politics",
10452
+ "religion",
10453
+ "ethnicity",
10454
+ "smoking",
10455
+ "drinking",
10456
+ "exercise",
10457
+ "sexuality",
10458
+ "prompt"
10459
+ ];
10460
+ var MEMORY_LEVELS = ["private", "matching", "profile"];
10461
+ var MemoryLevelError = class extends Error {
10462
+ constructor(message) {
10463
+ super(message);
10464
+ this.name = "MemoryLevelError";
10465
+ }
10466
+ };
10467
+ var MemorySourceIneligibleError = class extends Error {
10468
+ constructor() {
10469
+ super("Memory source is no longer eligible");
10470
+ this.name = "MemorySourceIneligibleError";
10471
+ }
10472
+ };
10473
+ var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
10474
+ function levelFromScope(scope) {
10475
+ return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
10476
+ }
10477
+ function scopeForLevel(level) {
10478
+ return level === "private" ? "private" : "shared";
10479
+ }
10480
+ function resolveMemoryLevel(level, scope) {
10481
+ return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
10482
+ }
10483
+ function levelForScopeChange(current, nextScope) {
10484
+ const implied = levelFromScope(nextScope);
10485
+ return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
10486
+ }
10487
+ function parseMedia(value) {
10488
+ if (typeof value !== "string" || value === "") return null;
10489
+ try {
10490
+ const parsed = JSON.parse(value);
10491
+ if (!Array.isArray(parsed)) return null;
10492
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
10493
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
10494
+ objectKey: r.objectKey ?? r.object_key ?? null
10495
+ })).filter((r) => Number.isFinite(r.feedItemId));
10496
+ return refs.length > 0 ? refs : null;
10497
+ } catch {
10498
+ return null;
10499
+ }
10500
+ }
10501
+
10441
10502
  // src/lib/db/entities/types.ts
10442
10503
  var ENTITY_KINDS = [
10443
10504
  "person",
@@ -10497,7 +10558,7 @@ function parseTopics(value) {
10497
10558
  // src/lib/db/entities/operations.ts
10498
10559
  async function assertCanWrite(ctx) {
10499
10560
  if (ctx.canWrite && !await ctx.canWrite()) {
10500
- throw new Error("Memory source is no longer eligible");
10561
+ throw new MemorySourceIneligibleError();
10501
10562
  }
10502
10563
  }
10503
10564
  function entityToStored(e) {
@@ -13139,61 +13200,6 @@ function serializeSourceChunkIds(ids) {
13139
13200
  return JSON.stringify(ids.slice(start));
13140
13201
  }
13141
13202
 
13142
- // src/lib/db/memoryVault/types.ts
13143
- var MEMORY_KINDS = [
13144
- "display_name",
13145
- "birth_date",
13146
- "bio",
13147
- "occupation",
13148
- "interest",
13149
- "gender",
13150
- "height_cm",
13151
- "looking_for",
13152
- "politics",
13153
- "religion",
13154
- "ethnicity",
13155
- "smoking",
13156
- "drinking",
13157
- "exercise",
13158
- "sexuality",
13159
- "prompt"
13160
- ];
13161
- var MEMORY_LEVELS = ["private", "matching", "profile"];
13162
- var MemoryLevelError = class extends Error {
13163
- constructor(message) {
13164
- super(message);
13165
- this.name = "MemoryLevelError";
13166
- }
13167
- };
13168
- var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
13169
- function levelFromScope(scope) {
13170
- return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
13171
- }
13172
- function scopeForLevel(level) {
13173
- return level === "private" ? "private" : "shared";
13174
- }
13175
- function resolveMemoryLevel(level, scope) {
13176
- return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
13177
- }
13178
- function levelForScopeChange(current, nextScope) {
13179
- const implied = levelFromScope(nextScope);
13180
- return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
13181
- }
13182
- function parseMedia(value) {
13183
- if (typeof value !== "string" || value === "") return null;
13184
- try {
13185
- const parsed = JSON.parse(value);
13186
- if (!Array.isArray(parsed)) return null;
13187
- const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
13188
- feedItemId: Number(r.feedItemId ?? r.feed_item_id),
13189
- objectKey: r.objectKey ?? r.object_key ?? null
13190
- })).filter((r) => Number.isFinite(r.feedItemId));
13191
- return refs.length > 0 ? refs : null;
13192
- } catch {
13193
- return null;
13194
- }
13195
- }
13196
-
13197
13203
  // src/lib/db/memoryVault/operations.ts
13198
13204
  function visibilityOrPrivate(value) {
13199
13205
  return value === "public" ? value : "private";
@@ -13213,7 +13219,7 @@ function isKinded(record2) {
13213
13219
  }
13214
13220
  async function assertCanWrite2(ctx) {
13215
13221
  if (ctx.canWrite && !await ctx.canWrite()) {
13216
- throw new Error("Memory source is no longer eligible");
13222
+ throw new MemorySourceIneligibleError();
13217
13223
  }
13218
13224
  }
13219
13225
  function assertValidKindLevel(kind, level) {
@@ -13904,7 +13910,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
13904
13910
  ctx.embeddedWalletSigner
13905
13911
  );
13906
13912
  } catch (err) {
13907
- if (err instanceof MemoryLevelError) throw err;
13913
+ if (err instanceof MemoryLevelError || err instanceof MemorySourceIneligibleError) throw err;
13908
13914
  return null;
13909
13915
  }
13910
13916
  }
@@ -17878,6 +17884,13 @@ var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
17878
17884
  var DEFAULT_SCOPE = "private";
17879
17885
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
17880
17886
  var DEFAULT_CONSOLIDATE_TOP_K = 20;
17887
+ var RetainError = class extends Error {
17888
+ constructor(reason, message) {
17889
+ super(message);
17890
+ this.reason = reason;
17891
+ this.name = "RetainError";
17892
+ }
17893
+ };
17881
17894
  async function retain(content, ctx, options = {}) {
17882
17895
  const embeddingOptions = {
17883
17896
  ...ctx.embeddingOptions,
@@ -17933,7 +17946,8 @@ async function retainWithPersistence(content, ctx, options = {}) {
17933
17946
  });
17934
17947
  prepared = withoutKindedRows(prepared);
17935
17948
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
17936
- throw new Error(
17949
+ throw new RetainError(
17950
+ "embeddings-unavailable",
17937
17951
  "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."
17938
17952
  );
17939
17953
  }
@@ -18303,7 +18317,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
18303
18317
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
18304
18318
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
18305
18319
  if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
18306
- throw new Error(`retain: merge into memory ${targetId} failed to persist`);
18320
+ throw new RetainError(
18321
+ "merge-not-persisted",
18322
+ `retain: merge into memory ${targetId} failed to persist`
18323
+ );
18307
18324
  }
18308
18325
  }
18309
18326
 
@@ -18461,6 +18478,12 @@ function restoreCandidates(candidates, redactor, ownNames) {
18461
18478
  (c) => c.candidate.content.length <= MAX_CONTENT_LENGTH && !c.unresolved && !isLowSignalContent(c.candidate.content, ownNames)
18462
18479
  ).map((c) => c.candidate);
18463
18480
  }
18481
+ function writeFailureReasonOf(err) {
18482
+ if (err instanceof MemorySourceIneligibleError) return "source-ineligible";
18483
+ if (err instanceof RetainError) return err.reason;
18484
+ if (err?.name === "AbortError") return "aborted";
18485
+ return "unknown";
18486
+ }
18464
18487
  async function extractAndRetain(messages, retainCtx, options) {
18465
18488
  const { memoryStore, signal } = options;
18466
18489
  if (memoryStore === null) throw new Error("Memory store is not ready");
@@ -18550,6 +18573,7 @@ async function extractAndRetain(messages, retainCtx, options) {
18550
18573
  const results = [];
18551
18574
  const quarantinedInfo = [];
18552
18575
  let failedWrites = 0;
18576
+ let writeFailureReason;
18553
18577
  let auditRows;
18554
18578
  const tRetain = Date.now();
18555
18579
  for (const { candidate, isQuarantined, reason, signature } of toRetain) {
@@ -18645,6 +18669,7 @@ async function extractAndRetain(messages, retainCtx, options) {
18645
18669
  }
18646
18670
  } catch (err) {
18647
18671
  failedWrites++;
18672
+ writeFailureReason ?? (writeFailureReason = writeFailureReasonOf(err));
18648
18673
  log.warn("[memory/extract] retain failed for one candidate", err);
18649
18674
  options.onCandidateFailed?.(candidate, err);
18650
18675
  }
@@ -18657,6 +18682,7 @@ async function extractAndRetain(messages, retainCtx, options) {
18657
18682
  candidates: succeededCandidates,
18658
18683
  results,
18659
18684
  failedCount: failedWrites,
18685
+ ...writeFailureReason !== void 0 && { writeFailureReason },
18660
18686
  outcome: outcome2,
18661
18687
  quarantined: quarantinedInfo,
18662
18688
  funnel: {
@@ -18925,7 +18951,17 @@ function createAutoExtractor(options) {
18925
18951
  const t0 = Date.now();
18926
18952
  void (async () => {
18927
18953
  try {
18928
- const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
18954
+ const {
18955
+ candidates,
18956
+ results,
18957
+ failedCount,
18958
+ writeFailureReason,
18959
+ outcome: outcome2,
18960
+ failure,
18961
+ funnel,
18962
+ timings,
18963
+ model
18964
+ } = await extractAndRetain(window2, retainCtx, {
18929
18965
  extract,
18930
18966
  memoryStore: options.memoryStore,
18931
18967
  signal: options.signal,
@@ -18961,6 +18997,7 @@ function createAutoExtractor(options) {
18961
18997
  candidates,
18962
18998
  results,
18963
18999
  failedCount,
19000
+ ...writeFailureReason !== void 0 && { writeFailureReason },
18964
19001
  durationMs: Date.now() - t0,
18965
19002
  conversationId,
18966
19003
  outcome: outcome2,
@@ -21073,10 +21110,10 @@ function createLocalMemoryStore(options) {
21073
21110
  const assertWrite = async (writeOptions) => {
21074
21111
  writeOptions?.signal?.throwIfAborted();
21075
21112
  if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
21076
- throw new Error("Memory source is no longer eligible");
21113
+ throw new MemorySourceIneligibleError();
21077
21114
  }
21078
21115
  if (options.canWrite && !await options.canWrite()) {
21079
- throw new Error("Memory source is no longer eligible");
21116
+ throw new MemorySourceIneligibleError();
21080
21117
  }
21081
21118
  writeOptions?.signal?.throwIfAborted();
21082
21119
  };
@@ -21885,7 +21922,7 @@ function createRemoteMemoryPipeline(options) {
21885
21922
  const assertWrite = async () => {
21886
21923
  signal?.throwIfAborted();
21887
21924
  if (writeOptions?.canWrite && !await writeOptions.canWrite())
21888
- throw new Error("Memory source is no longer eligible");
21925
+ throw new MemorySourceIneligibleError();
21889
21926
  signal?.throwIfAborted();
21890
21927
  };
21891
21928
  const rejectUndecryptable = (failed) => {
@@ -22891,7 +22928,7 @@ function createRemoteMemoryStore(options) {
22891
22928
  if (!record2) return null;
22892
22929
  if (record2.memory.is_deleted) return null;
22893
22930
  if (writeOptions?.canWrite && !await writeOptions.canWrite())
22894
- throw new Error("Memory source is no longer eligible");
22931
+ throw new MemorySourceIneligibleError();
22895
22932
  writeOptions?.signal?.throwIfAborted();
22896
22933
  const next = edit(structuredClone(record2.memory));
22897
22934
  if (!next) return null;
@@ -24519,6 +24556,26 @@ function createDurableAutoExtractor(options) {
24519
24556
  );
24520
24557
  continue;
24521
24558
  }
24559
+ const foreign = new Set(
24560
+ ids.filter((_id, index) => loaded[index]?.conversationId !== conversationId)
24561
+ );
24562
+ if (foreign.size) {
24563
+ await database.write(
24564
+ () => job.update(
24565
+ (r) => r._setRaw(
24566
+ "message_ids",
24567
+ JSON.stringify(idsOf(job).filter((id) => !foreign.has(id)))
24568
+ )
24569
+ )
24570
+ );
24571
+ attempts.delete(job.id);
24572
+ scheduleAfterSuccess = true;
24573
+ reportError(
24574
+ new Error(`Dropped ${foreign.size} source id(s) from another conversation`),
24575
+ conversationId
24576
+ );
24577
+ continue;
24578
+ }
24522
24579
  const locked = loaded.filter((message) => message && isEncrypted(message.content));
24523
24580
  if (locked.length) {
24524
24581
  throw new LockedSourcesError(
@@ -24528,7 +24585,7 @@ function createDurableAutoExtractor(options) {
24528
24585
  );
24529
24586
  }
24530
24587
  const messages = loaded.flatMap(
24531
- (m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
24588
+ (m) => m && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
24532
24589
  );
24533
24590
  const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
24534
24591
  const jobFolderId = job._getRaw("folder_id") ?? null;
@@ -24621,9 +24678,31 @@ function createDurableAutoExtractor(options) {
24621
24678
  (candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
24622
24679
  );
24623
24680
  const positions = new Map(ids.map((id, index) => [id, index]));
24681
+ const watermarks = existing.flatMap((prior) => {
24682
+ const watermark = prior._getRaw("watermark");
24683
+ return typeof watermark === "string" && watermark ? [watermark] : [];
24684
+ });
24685
+ if (watermarks.length) {
24686
+ const misplaced = new Set(
24687
+ await storage.messagesCollection.query(
24688
+ Q16.where("id", Q16.oneOf(watermarks)),
24689
+ Q16.where("conversation_id", Q16.notEq(conversationId))
24690
+ ).fetchIds()
24691
+ );
24692
+ for (const prior of existing)
24693
+ if (misplaced.has(String(prior._getRaw("watermark"))))
24694
+ await prior.update((r) => {
24695
+ r._setRaw("watermark", null);
24696
+ r._setRaw("watermark_seq", null);
24697
+ });
24698
+ }
24624
24699
  const rows = await storage.messagesCollection.query(Q16.where("id", Q16.oneOf(ids))).fetch();
24700
+ const foreignRows = new Set(
24701
+ rows.filter((row) => row._getRaw("conversation_id") !== conversationId).map((row) => row.id)
24702
+ );
24625
24703
  const sequences = /* @__PURE__ */ new Map();
24626
24704
  for (const row of rows) {
24705
+ if (foreignRows.has(row.id)) continue;
24627
24706
  const sequence = Number(row._getRaw("message_id"));
24628
24707
  if (Number.isFinite(sequence) && sequence > 0) sequences.set(row.id, sequence);
24629
24708
  }
@@ -24666,7 +24745,7 @@ function createDurableAutoExtractor(options) {
24666
24745
  const ownWatermark = job?._getRaw("watermark");
24667
24746
  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));
24668
24747
  const overlapStart = atOwnWatermark ? Math.max(0, boundary - 1) : start;
24669
- const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id));
24748
+ const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id) && !foreignRows.has(id));
24670
24749
  if (!fresh.length) return;
24671
24750
  if (job) {
24672
24751
  await job.update(