@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.
@@ -27777,6 +27777,67 @@ init_logger();
27777
27777
  // src/lib/db/entities/operations.ts
27778
27778
  var import_watermelondb18 = __toESM(require_watermelondb());
27779
27779
 
27780
+ // src/lib/db/memoryVault/types.ts
27781
+ var MEMORY_KINDS = [
27782
+ "display_name",
27783
+ "birth_date",
27784
+ "bio",
27785
+ "occupation",
27786
+ "interest",
27787
+ "gender",
27788
+ "height_cm",
27789
+ "looking_for",
27790
+ "politics",
27791
+ "religion",
27792
+ "ethnicity",
27793
+ "smoking",
27794
+ "drinking",
27795
+ "exercise",
27796
+ "sexuality",
27797
+ "prompt"
27798
+ ];
27799
+ var MEMORY_LEVELS = ["private", "matching", "profile"];
27800
+ var MemoryLevelError = class extends Error {
27801
+ constructor(message) {
27802
+ super(message);
27803
+ this.name = "MemoryLevelError";
27804
+ }
27805
+ };
27806
+ var MemorySourceIneligibleError = class extends Error {
27807
+ constructor() {
27808
+ super("Memory source is no longer eligible");
27809
+ this.name = "MemorySourceIneligibleError";
27810
+ }
27811
+ };
27812
+ var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
27813
+ function levelFromScope(scope) {
27814
+ return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
27815
+ }
27816
+ function scopeForLevel(level) {
27817
+ return level === "private" ? "private" : "shared";
27818
+ }
27819
+ function resolveMemoryLevel(level, scope) {
27820
+ return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
27821
+ }
27822
+ function levelForScopeChange(current, nextScope) {
27823
+ const implied = levelFromScope(nextScope);
27824
+ return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
27825
+ }
27826
+ function parseMedia(value) {
27827
+ if (typeof value !== "string" || value === "") return null;
27828
+ try {
27829
+ const parsed = JSON.parse(value);
27830
+ if (!Array.isArray(parsed)) return null;
27831
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
27832
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
27833
+ objectKey: r.objectKey ?? r.object_key ?? null
27834
+ })).filter((r) => Number.isFinite(r.feedItemId));
27835
+ return refs.length > 0 ? refs : null;
27836
+ } catch {
27837
+ return null;
27838
+ }
27839
+ }
27840
+
27780
27841
  // src/lib/db/entities/types.ts
27781
27842
  var ENTITY_KINDS = [
27782
27843
  "person",
@@ -27826,7 +27887,7 @@ function parseTopics(value) {
27826
27887
  // src/lib/db/entities/operations.ts
27827
27888
  async function assertCanWrite(ctx) {
27828
27889
  if (ctx.canWrite && !await ctx.canWrite()) {
27829
- throw new Error("Memory source is no longer eligible");
27890
+ throw new MemorySourceIneligibleError();
27830
27891
  }
27831
27892
  }
27832
27893
  function entityToStored(e) {
@@ -28219,61 +28280,6 @@ function serializeSourceChunkIds(ids) {
28219
28280
  return JSON.stringify(ids.slice(start));
28220
28281
  }
28221
28282
 
28222
- // src/lib/db/memoryVault/types.ts
28223
- var MEMORY_KINDS = [
28224
- "display_name",
28225
- "birth_date",
28226
- "bio",
28227
- "occupation",
28228
- "interest",
28229
- "gender",
28230
- "height_cm",
28231
- "looking_for",
28232
- "politics",
28233
- "religion",
28234
- "ethnicity",
28235
- "smoking",
28236
- "drinking",
28237
- "exercise",
28238
- "sexuality",
28239
- "prompt"
28240
- ];
28241
- var MEMORY_LEVELS = ["private", "matching", "profile"];
28242
- var MemoryLevelError = class extends Error {
28243
- constructor(message) {
28244
- super(message);
28245
- this.name = "MemoryLevelError";
28246
- }
28247
- };
28248
- var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
28249
- function levelFromScope(scope) {
28250
- return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
28251
- }
28252
- function scopeForLevel(level) {
28253
- return level === "private" ? "private" : "shared";
28254
- }
28255
- function resolveMemoryLevel(level, scope) {
28256
- return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
28257
- }
28258
- function levelForScopeChange(current, nextScope) {
28259
- const implied = levelFromScope(nextScope);
28260
- return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
28261
- }
28262
- function parseMedia(value) {
28263
- if (typeof value !== "string" || value === "") return null;
28264
- try {
28265
- const parsed = JSON.parse(value);
28266
- if (!Array.isArray(parsed)) return null;
28267
- const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
28268
- feedItemId: Number(r.feedItemId ?? r.feed_item_id),
28269
- objectKey: r.objectKey ?? r.object_key ?? null
28270
- })).filter((r) => Number.isFinite(r.feedItemId));
28271
- return refs.length > 0 ? refs : null;
28272
- } catch {
28273
- return null;
28274
- }
28275
- }
28276
-
28277
28283
  // src/lib/db/memoryVault/operations.ts
28278
28284
  function visibilityOrPrivate(value) {
28279
28285
  return value === "public" ? value : "private";
@@ -28293,7 +28299,7 @@ function isKinded(record) {
28293
28299
  }
28294
28300
  async function assertCanWrite2(ctx) {
28295
28301
  if (ctx.canWrite && !await ctx.canWrite()) {
28296
- throw new Error("Memory source is no longer eligible");
28302
+ throw new MemorySourceIneligibleError();
28297
28303
  }
28298
28304
  }
28299
28305
  function assertValidKindLevel(kind, level) {
@@ -28970,7 +28976,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
28970
28976
  ctx.embeddedWalletSigner
28971
28977
  );
28972
28978
  } catch (err) {
28973
- if (err instanceof MemoryLevelError) throw err;
28979
+ if (err instanceof MemoryLevelError || err instanceof MemorySourceIneligibleError) throw err;
28974
28980
  return null;
28975
28981
  }
28976
28982
  }
@@ -32667,6 +32673,13 @@ var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
32667
32673
  var DEFAULT_SCOPE = "private";
32668
32674
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
32669
32675
  var DEFAULT_CONSOLIDATE_TOP_K = 20;
32676
+ var RetainError = class extends Error {
32677
+ constructor(reason, message) {
32678
+ super(message);
32679
+ this.reason = reason;
32680
+ this.name = "RetainError";
32681
+ }
32682
+ };
32670
32683
  async function retain(content, ctx, options = {}) {
32671
32684
  const embeddingOptions = {
32672
32685
  ...ctx.embeddingOptions,
@@ -32722,7 +32735,8 @@ async function retainWithPersistence(content, ctx, options = {}) {
32722
32735
  });
32723
32736
  prepared = withoutKindedRows(prepared);
32724
32737
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
32725
- throw new Error(
32738
+ throw new RetainError(
32739
+ "embeddings-unavailable",
32726
32740
  "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."
32727
32741
  );
32728
32742
  }
@@ -33092,7 +33106,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
33092
33106
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
33093
33107
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
33094
33108
  if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
33095
- throw new Error(`retain: merge into memory ${targetId} failed to persist`);
33109
+ throw new RetainError(
33110
+ "merge-not-persisted",
33111
+ `retain: merge into memory ${targetId} failed to persist`
33112
+ );
33096
33113
  }
33097
33114
  }
33098
33115
 
@@ -33250,6 +33267,12 @@ function restoreCandidates(candidates, redactor, ownNames) {
33250
33267
  (c) => c.candidate.content.length <= MAX_CONTENT_LENGTH && !c.unresolved && !isLowSignalContent(c.candidate.content, ownNames)
33251
33268
  ).map((c) => c.candidate);
33252
33269
  }
33270
+ function writeFailureReasonOf(err) {
33271
+ if (err instanceof MemorySourceIneligibleError) return "source-ineligible";
33272
+ if (err instanceof RetainError) return err.reason;
33273
+ if (err?.name === "AbortError") return "aborted";
33274
+ return "unknown";
33275
+ }
33253
33276
  async function extractAndRetain(messages, retainCtx, options) {
33254
33277
  const { memoryStore, signal } = options;
33255
33278
  if (memoryStore === null) throw new Error("Memory store is not ready");
@@ -33339,6 +33362,7 @@ async function extractAndRetain(messages, retainCtx, options) {
33339
33362
  const results = [];
33340
33363
  const quarantinedInfo = [];
33341
33364
  let failedWrites = 0;
33365
+ let writeFailureReason;
33342
33366
  let auditRows;
33343
33367
  const tRetain = Date.now();
33344
33368
  for (const { candidate, isQuarantined, reason, signature } of toRetain) {
@@ -33434,6 +33458,7 @@ async function extractAndRetain(messages, retainCtx, options) {
33434
33458
  }
33435
33459
  } catch (err) {
33436
33460
  failedWrites++;
33461
+ writeFailureReason ?? (writeFailureReason = writeFailureReasonOf(err));
33437
33462
  log.warn("[memory/extract] retain failed for one candidate", err);
33438
33463
  options.onCandidateFailed?.(candidate, err);
33439
33464
  }
@@ -33446,6 +33471,7 @@ async function extractAndRetain(messages, retainCtx, options) {
33446
33471
  candidates: succeededCandidates,
33447
33472
  results,
33448
33473
  failedCount: failedWrites,
33474
+ ...writeFailureReason !== void 0 && { writeFailureReason },
33449
33475
  outcome,
33450
33476
  quarantined: quarantinedInfo,
33451
33477
  funnel: {
@@ -33716,7 +33742,17 @@ function createAutoExtractor(options) {
33716
33742
  const t0 = Date.now();
33717
33743
  void (async () => {
33718
33744
  try {
33719
- const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
33745
+ const {
33746
+ candidates,
33747
+ results,
33748
+ failedCount,
33749
+ writeFailureReason,
33750
+ outcome,
33751
+ failure,
33752
+ funnel,
33753
+ timings,
33754
+ model
33755
+ } = await extractAndRetain(window2, retainCtx, {
33720
33756
  extract,
33721
33757
  memoryStore: options.memoryStore,
33722
33758
  signal: options.signal,
@@ -33752,6 +33788,7 @@ function createAutoExtractor(options) {
33752
33788
  candidates,
33753
33789
  results,
33754
33790
  failedCount,
33791
+ ...writeFailureReason !== void 0 && { writeFailureReason },
33755
33792
  durationMs: Date.now() - t0,
33756
33793
  conversationId,
33757
33794
  outcome,
@@ -35883,10 +35920,10 @@ function createLocalMemoryStore(options) {
35883
35920
  const assertWrite = async (writeOptions) => {
35884
35921
  writeOptions?.signal?.throwIfAborted();
35885
35922
  if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
35886
- throw new Error("Memory source is no longer eligible");
35923
+ throw new MemorySourceIneligibleError();
35887
35924
  }
35888
35925
  if (options.canWrite && !await options.canWrite()) {
35889
- throw new Error("Memory source is no longer eligible");
35926
+ throw new MemorySourceIneligibleError();
35890
35927
  }
35891
35928
  writeOptions?.signal?.throwIfAborted();
35892
35929
  };
@@ -37133,6 +37170,26 @@ function createDurableAutoExtractor(options) {
37133
37170
  );
37134
37171
  continue;
37135
37172
  }
37173
+ const foreign = new Set(
37174
+ ids.filter((_id, index) => loaded[index]?.conversationId !== conversationId)
37175
+ );
37176
+ if (foreign.size) {
37177
+ await database.write(
37178
+ () => job.update(
37179
+ (r) => r._setRaw(
37180
+ "message_ids",
37181
+ JSON.stringify(idsOf(job).filter((id) => !foreign.has(id)))
37182
+ )
37183
+ )
37184
+ );
37185
+ attempts.delete(job.id);
37186
+ scheduleAfterSuccess = true;
37187
+ reportError(
37188
+ new Error(`Dropped ${foreign.size} source id(s) from another conversation`),
37189
+ conversationId
37190
+ );
37191
+ continue;
37192
+ }
37136
37193
  const locked = loaded.filter((message) => message && isEncrypted(message.content));
37137
37194
  if (locked.length) {
37138
37195
  throw new LockedSourcesError(
@@ -37142,7 +37199,7 @@ function createDurableAutoExtractor(options) {
37142
37199
  );
37143
37200
  }
37144
37201
  const messages = loaded.flatMap(
37145
- (m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
37202
+ (m) => m && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
37146
37203
  );
37147
37204
  const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
37148
37205
  const jobFolderId = job._getRaw("folder_id") ?? null;
@@ -37235,9 +37292,31 @@ function createDurableAutoExtractor(options) {
37235
37292
  (candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
37236
37293
  );
37237
37294
  const positions = new Map(ids.map((id, index) => [id, index]));
37295
+ const watermarks = existing.flatMap((prior) => {
37296
+ const watermark = prior._getRaw("watermark");
37297
+ return typeof watermark === "string" && watermark ? [watermark] : [];
37298
+ });
37299
+ if (watermarks.length) {
37300
+ const misplaced = new Set(
37301
+ await storage.messagesCollection.query(
37302
+ import_watermelondb25.Q.where("id", import_watermelondb25.Q.oneOf(watermarks)),
37303
+ import_watermelondb25.Q.where("conversation_id", import_watermelondb25.Q.notEq(conversationId))
37304
+ ).fetchIds()
37305
+ );
37306
+ for (const prior of existing)
37307
+ if (misplaced.has(String(prior._getRaw("watermark"))))
37308
+ await prior.update((r) => {
37309
+ r._setRaw("watermark", null);
37310
+ r._setRaw("watermark_seq", null);
37311
+ });
37312
+ }
37238
37313
  const rows = await storage.messagesCollection.query(import_watermelondb25.Q.where("id", import_watermelondb25.Q.oneOf(ids))).fetch();
37314
+ const foreignRows = new Set(
37315
+ rows.filter((row) => row._getRaw("conversation_id") !== conversationId).map((row) => row.id)
37316
+ );
37239
37317
  const sequences = /* @__PURE__ */ new Map();
37240
37318
  for (const row of rows) {
37319
+ if (foreignRows.has(row.id)) continue;
37241
37320
  const sequence = Number(row._getRaw("message_id"));
37242
37321
  if (Number.isFinite(sequence) && sequence > 0) sequences.set(row.id, sequence);
37243
37322
  }
@@ -37280,7 +37359,7 @@ function createDurableAutoExtractor(options) {
37280
37359
  const ownWatermark = job?._getRaw("watermark");
37281
37360
  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));
37282
37361
  const overlapStart = atOwnWatermark ? Math.max(0, boundary - 1) : start;
37283
- const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id));
37362
+ const fresh = ids.slice(overlapStart).filter((id) => !foreignSources.has(id) && !foreignRows.has(id));
37284
37363
  if (!fresh.length) return;
37285
37364
  if (job) {
37286
37365
  await job.update(
@@ -4931,6 +4931,7 @@ declare function extractFacts(messages: AutoExtractMessage[], options: ExtractFa
4931
4931
  * look like `no-facts`.
4932
4932
  */
4933
4933
  type ExtractOutcome = "extracted" | "no-facts" | "empty-after-retry" | "dropped-after-redaction";
4934
+ type WriteFailureReason = "source-ineligible" | "embeddings-unavailable" | "merge-not-persisted" | "aborted" | "unknown";
4934
4935
  /**
4935
4936
  * Stage 2 — for each extracted candidate, call retain() with auto-merge
4936
4937
  * enabled. When `consolidateOptions` are wired, retain()'s consolidation pass
@@ -5001,6 +5002,7 @@ declare function extractAndRetain(messages: AutoExtractMessage[], retainCtx: Ret
5001
5002
  candidates: ExtractedCandidate[];
5002
5003
  results: RetainResult[];
5003
5004
  failedCount: number;
5005
+ writeFailureReason?: WriteFailureReason;
5004
5006
  outcome: ExtractOutcome;
5005
5007
  /**
5006
5008
  * Tier-0 security (PR3) — candidates quarantined by the injection screen and
@@ -9036,6 +9038,7 @@ interface TurnCompleteEvent {
9036
9038
  results: RetainResult[];
9037
9039
  /** Per-candidate retain() failures. `onError` only fires on pipeline throws. */
9038
9040
  failedCount: number;
9041
+ writeFailureReason?: WriteFailureReason;
9039
9042
  durationMs: number;
9040
9043
  conversationId?: string;
9041
9044
  /**
@@ -4931,6 +4931,7 @@ declare function extractFacts(messages: AutoExtractMessage[], options: ExtractFa
4931
4931
  * look like `no-facts`.
4932
4932
  */
4933
4933
  type ExtractOutcome = "extracted" | "no-facts" | "empty-after-retry" | "dropped-after-redaction";
4934
+ type WriteFailureReason = "source-ineligible" | "embeddings-unavailable" | "merge-not-persisted" | "aborted" | "unknown";
4934
4935
  /**
4935
4936
  * Stage 2 — for each extracted candidate, call retain() with auto-merge
4936
4937
  * enabled. When `consolidateOptions` are wired, retain()'s consolidation pass
@@ -5001,6 +5002,7 @@ declare function extractAndRetain(messages: AutoExtractMessage[], retainCtx: Ret
5001
5002
  candidates: ExtractedCandidate[];
5002
5003
  results: RetainResult[];
5003
5004
  failedCount: number;
5005
+ writeFailureReason?: WriteFailureReason;
5004
5006
  outcome: ExtractOutcome;
5005
5007
  /**
5006
5008
  * Tier-0 security (PR3) — candidates quarantined by the injection screen and
@@ -9036,6 +9038,7 @@ interface TurnCompleteEvent {
9036
9038
  results: RetainResult[];
9037
9039
  /** Per-candidate retain() failures. `onError` only fires on pipeline throws. */
9038
9040
  failedCount: number;
9041
+ writeFailureReason?: WriteFailureReason;
9039
9042
  durationMs: number;
9040
9043
  conversationId?: string;
9041
9044
  /**