@anuma/sdk 10.6.0 → 10.6.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.
@@ -18537,6 +18537,52 @@ async function getDecayCandidatesRawOp(ctx) {
18537
18537
  trustTier: raw.trust_tier ?? null
18538
18538
  }));
18539
18539
  }
18540
+ async function applyDecayTransitionsOp(ctx, candidates, opts) {
18541
+ assertVaultScopeForSweep(ctx);
18542
+ const byId = new Map(candidates.map((candidate) => [candidate.uniqueId, candidate]));
18543
+ const ids = Array.from(byId.keys());
18544
+ const changed = /* @__PURE__ */ new Set();
18545
+ const CHUNK = 500;
18546
+ for (let i = 0; i < ids.length; i += CHUNK) {
18547
+ let applied = [];
18548
+ try {
18549
+ await ctx.database.write(async () => {
18550
+ await assertCanWrite2(ctx);
18551
+ const records = await ctx.vaultMemoryCollection.query(
18552
+ import_watermelondb21.Q.where("id", import_watermelondb21.Q.oneOf(ids.slice(i, i + CHUNK))),
18553
+ ...ctx.userId !== void 0 ? [import_watermelondb21.Q.where("user_id", ctx.userId)] : []
18554
+ ).fetch();
18555
+ const eligible = records.filter((record2) => {
18556
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
18557
+ if (opts.transition === "delete") {
18558
+ return record2.archivedAt !== null && opts.now - record2.archivedAt > opts.hardDeleteWindowMs;
18559
+ }
18560
+ const candidate = byId.get(record2.id);
18561
+ return record2.archivedAt === null && record2.updatedAt.getTime() === candidate.updatedAt && (record2.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
18562
+ });
18563
+ const prepared = eligible.map(
18564
+ (record2) => record2.prepareUpdate((row) => {
18565
+ if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
18566
+ else row._setRaw("is_deleted", true);
18567
+ })
18568
+ );
18569
+ if (prepared.length > 0) await ctx.database.batch(prepared);
18570
+ applied = eligible.map((record2) => record2.id);
18571
+ });
18572
+ } catch {
18573
+ continue;
18574
+ }
18575
+ for (const id2 of applied) changed.add(id2);
18576
+ if (opts.transition === "delete" && ctx.entityCtx) {
18577
+ try {
18578
+ await unlinkMemoryEntitiesOp(ctx.entityCtx, applied);
18579
+ } catch {
18580
+ continue;
18581
+ }
18582
+ }
18583
+ }
18584
+ return changed;
18585
+ }
18540
18586
  async function archiveVaultMemoryOp(ctx, id2, opts) {
18541
18587
  try {
18542
18588
  const record2 = await ctx.vaultMemoryCollection.find(id2);
@@ -23137,25 +23183,8 @@ function isBorderline(input) {
23137
23183
  function vaultDecayBackend(vaultCtx) {
23138
23184
  return {
23139
23185
  candidates: () => getDecayCandidatesRawOp(vaultCtx),
23140
- archive: async (rows, now) => {
23141
- const archived = /* @__PURE__ */ new Set();
23142
- for (const c of rows) {
23143
- const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
23144
- now,
23145
- expectedUpdatedAt: c.updatedAt,
23146
- expectedLastObservedAt: c.lastObservedAt ?? null
23147
- });
23148
- if (ok) archived.add(c.uniqueId);
23149
- }
23150
- return archived;
23151
- },
23152
- hardDelete: async (rows, deleteOptions) => {
23153
- const deleted = /* @__PURE__ */ new Set();
23154
- for (const c of rows) {
23155
- if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
23156
- }
23157
- return deleted;
23158
- }
23186
+ archive: (rows, now) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "archive", now }),
23187
+ hardDelete: (rows, deleteOptions) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "delete", ...deleteOptions })
23159
23188
  };
23160
23189
  }
23161
23190
  function createDecaySweeper(options) {
@@ -25157,6 +25186,7 @@ function createLocalMemoryStore(options) {
25157
25186
  "trust_tier",
25158
25187
  "superseded_by",
25159
25188
  "visibility",
25189
+ "twin_opt_in",
25160
25190
  "published_at",
25161
25191
  "geohash",
25162
25192
  "topics",
@@ -26348,6 +26378,7 @@ function subscriptionState({ memory, version }) {
26348
26378
  memory.event_time_kind,
26349
26379
  memory.trust_tier,
26350
26380
  memory.visibility,
26381
+ memory.twin_opt_in,
26351
26382
  memory.published_at,
26352
26383
  memory.geohash,
26353
26384
  memory.topics,
@@ -16867,6 +16867,52 @@ async function getDecayCandidatesRawOp(ctx) {
16867
16867
  trustTier: raw.trust_tier ?? null
16868
16868
  }));
16869
16869
  }
16870
+ async function applyDecayTransitionsOp(ctx, candidates, opts) {
16871
+ assertVaultScopeForSweep(ctx);
16872
+ const byId = new Map(candidates.map((candidate) => [candidate.uniqueId, candidate]));
16873
+ const ids = Array.from(byId.keys());
16874
+ const changed = /* @__PURE__ */ new Set();
16875
+ const CHUNK = 500;
16876
+ for (let i = 0; i < ids.length; i += CHUNK) {
16877
+ let applied = [];
16878
+ try {
16879
+ await ctx.database.write(async () => {
16880
+ await assertCanWrite2(ctx);
16881
+ const records = await ctx.vaultMemoryCollection.query(
16882
+ Q6.where("id", Q6.oneOf(ids.slice(i, i + CHUNK))),
16883
+ ...ctx.userId !== void 0 ? [Q6.where("user_id", ctx.userId)] : []
16884
+ ).fetch();
16885
+ const eligible = records.filter((record2) => {
16886
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
16887
+ if (opts.transition === "delete") {
16888
+ return record2.archivedAt !== null && opts.now - record2.archivedAt > opts.hardDeleteWindowMs;
16889
+ }
16890
+ const candidate = byId.get(record2.id);
16891
+ return record2.archivedAt === null && record2.updatedAt.getTime() === candidate.updatedAt && (record2.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
16892
+ });
16893
+ const prepared = eligible.map(
16894
+ (record2) => record2.prepareUpdate((row) => {
16895
+ if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
16896
+ else row._setRaw("is_deleted", true);
16897
+ })
16898
+ );
16899
+ if (prepared.length > 0) await ctx.database.batch(prepared);
16900
+ applied = eligible.map((record2) => record2.id);
16901
+ });
16902
+ } catch {
16903
+ continue;
16904
+ }
16905
+ for (const id2 of applied) changed.add(id2);
16906
+ if (opts.transition === "delete" && ctx.entityCtx) {
16907
+ try {
16908
+ await unlinkMemoryEntitiesOp(ctx.entityCtx, applied);
16909
+ } catch {
16910
+ continue;
16911
+ }
16912
+ }
16913
+ }
16914
+ return changed;
16915
+ }
16870
16916
  async function archiveVaultMemoryOp(ctx, id2, opts) {
16871
16917
  try {
16872
16918
  const record2 = await ctx.vaultMemoryCollection.find(id2);
@@ -21436,25 +21482,8 @@ function isBorderline(input) {
21436
21482
  function vaultDecayBackend(vaultCtx) {
21437
21483
  return {
21438
21484
  candidates: () => getDecayCandidatesRawOp(vaultCtx),
21439
- archive: async (rows, now) => {
21440
- const archived = /* @__PURE__ */ new Set();
21441
- for (const c of rows) {
21442
- const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
21443
- now,
21444
- expectedUpdatedAt: c.updatedAt,
21445
- expectedLastObservedAt: c.lastObservedAt ?? null
21446
- });
21447
- if (ok) archived.add(c.uniqueId);
21448
- }
21449
- return archived;
21450
- },
21451
- hardDelete: async (rows, deleteOptions) => {
21452
- const deleted = /* @__PURE__ */ new Set();
21453
- for (const c of rows) {
21454
- if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
21455
- }
21456
- return deleted;
21457
- }
21485
+ archive: (rows, now) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "archive", now }),
21486
+ hardDelete: (rows, deleteOptions) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "delete", ...deleteOptions })
21458
21487
  };
21459
21488
  }
21460
21489
  function createDecaySweeper(options) {
@@ -23441,6 +23470,7 @@ function createLocalMemoryStore(options) {
23441
23470
  "trust_tier",
23442
23471
  "superseded_by",
23443
23472
  "visibility",
23473
+ "twin_opt_in",
23444
23474
  "published_at",
23445
23475
  "geohash",
23446
23476
  "topics",
@@ -24627,6 +24657,7 @@ function subscriptionState({ memory, version }) {
24627
24657
  memory.event_time_kind,
24628
24658
  memory.trust_tier,
24629
24659
  memory.visibility,
24660
+ memory.twin_opt_in,
24630
24661
  memory.published_at,
24631
24662
  memory.geohash,
24632
24663
  memory.topics,
@@ -42,20 +42,24 @@ var DEFAULT_TAG_MAP = {
42
42
  MISC: void 0
43
43
  };
44
44
  function placeTokens(tokens, text) {
45
- const placed = [];
45
+ return tokens.map((token) => {
46
+ const { start = -1, end = -1 } = token;
47
+ return Number.isInteger(start) && Number.isInteger(end) && start >= 0 && end > start && end <= text.length ? { ...token, start, end } : { ...token, start: -1, end: -1 };
48
+ });
49
+ }
50
+ function tokenOffsets(text, tokenizer) {
51
+ const { input_ids } = tokenizer(text, { return_tensor: false, truncation: true });
46
52
  let cursor = 0;
47
- for (const t of tokens) {
48
- const surface = t.word.startsWith("##") ? t.word.slice(2) : t.word;
53
+ return input_ids.map((id) => {
54
+ const word = tokenizer.decode([id], { skip_special_tokens: true });
55
+ const surface = word.startsWith("##") ? word.slice(2) : word;
56
+ if (!surface) return { start: -1, end: -1 };
49
57
  const start = text.indexOf(surface, cursor);
50
- if (start < 0) {
51
- placed.push({ ...t, start: -1, end: -1 });
52
- continue;
53
- }
58
+ if (start < 0) return { start: -1, end: -1 };
54
59
  const end = start + surface.length;
55
- placed.push({ ...t, start, end });
56
60
  cursor = end;
57
- }
58
- return placed;
61
+ return { start, end };
62
+ });
59
63
  }
60
64
  function aggregateTokens(tokens, text, tagMap, minScore) {
61
65
  const placed = placeTokens(tokens, text);
@@ -115,7 +119,14 @@ function createTransformersNerDetector(options = {}) {
115
119
  if (!text) return [];
116
120
  const classify = await load();
117
121
  const tokens = await classify(text);
118
- return aggregateTokens(tokens, text, tagMap, minScore);
122
+ if (!tokens.length) return [];
123
+ const offsets = tokenOffsets(text, classify.tokenizer);
124
+ return aggregateTokens(
125
+ tokens.map((token) => ({ ...token, ...offsets[token.index] })),
126
+ text,
127
+ tagMap,
128
+ minScore
129
+ );
119
130
  }
120
131
  };
121
132
  }
@@ -54,13 +54,10 @@ interface RawToken {
54
54
  score: number;
55
55
  index: number;
56
56
  word: string;
57
+ start?: number;
58
+ end?: number;
57
59
  }
58
- /**
59
- * Aggregate B-/I- subword tokens into whole-entity spans. A new entity starts
60
- * on a `B-` tag or a tag change; contiguous `I-` tokens (and WordPiece "##"
61
- * continuations) of the same base tag extend it. (The SDK additionally snaps
62
- * spans to word boundaries, so dropped trailing subwords are recovered there.)
63
- */
60
+ /** Aggregate classified tokens with character offsets into whole-entity spans. */
64
61
  declare function aggregateTokens(tokens: RawToken[], text: string, tagMap: Record<string, string | undefined>, minScore: number): PiiSpan[];
65
62
  /**
66
63
  * Create a Transformers.js-backed {@link NerDetector}. The returned detector
@@ -54,13 +54,10 @@ interface RawToken {
54
54
  score: number;
55
55
  index: number;
56
56
  word: string;
57
+ start?: number;
58
+ end?: number;
57
59
  }
58
- /**
59
- * Aggregate B-/I- subword tokens into whole-entity spans. A new entity starts
60
- * on a `B-` tag or a tag change; contiguous `I-` tokens (and WordPiece "##"
61
- * continuations) of the same base tag extend it. (The SDK additionally snaps
62
- * spans to word boundaries, so dropped trailing subwords are recovered there.)
63
- */
60
+ /** Aggregate classified tokens with character offsets into whole-entity spans. */
64
61
  declare function aggregateTokens(tokens: RawToken[], text: string, tagMap: Record<string, string | undefined>, minScore: number): PiiSpan[];
65
62
  /**
66
63
  * Create a Transformers.js-backed {@link NerDetector}. The returned detector
@@ -7,20 +7,24 @@ var DEFAULT_TAG_MAP = {
7
7
  MISC: void 0
8
8
  };
9
9
  function placeTokens(tokens, text) {
10
- const placed = [];
10
+ return tokens.map((token) => {
11
+ const { start = -1, end = -1 } = token;
12
+ return Number.isInteger(start) && Number.isInteger(end) && start >= 0 && end > start && end <= text.length ? { ...token, start, end } : { ...token, start: -1, end: -1 };
13
+ });
14
+ }
15
+ function tokenOffsets(text, tokenizer) {
16
+ const { input_ids } = tokenizer(text, { return_tensor: false, truncation: true });
11
17
  let cursor = 0;
12
- for (const t of tokens) {
13
- const surface = t.word.startsWith("##") ? t.word.slice(2) : t.word;
18
+ return input_ids.map((id) => {
19
+ const word = tokenizer.decode([id], { skip_special_tokens: true });
20
+ const surface = word.startsWith("##") ? word.slice(2) : word;
21
+ if (!surface) return { start: -1, end: -1 };
14
22
  const start = text.indexOf(surface, cursor);
15
- if (start < 0) {
16
- placed.push({ ...t, start: -1, end: -1 });
17
- continue;
18
- }
23
+ if (start < 0) return { start: -1, end: -1 };
19
24
  const end = start + surface.length;
20
- placed.push({ ...t, start, end });
21
25
  cursor = end;
22
- }
23
- return placed;
26
+ return { start, end };
27
+ });
24
28
  }
25
29
  function aggregateTokens(tokens, text, tagMap, minScore) {
26
30
  const placed = placeTokens(tokens, text);
@@ -80,7 +84,14 @@ function createTransformersNerDetector(options = {}) {
80
84
  if (!text) return [];
81
85
  const classify = await load();
82
86
  const tokens = await classify(text);
83
- return aggregateTokens(tokens, text, tagMap, minScore);
87
+ if (!tokens.length) return [];
88
+ const offsets = tokenOffsets(text, classify.tokenizer);
89
+ return aggregateTokens(
90
+ tokens.map((token) => ({ ...token, ...offsets[token.index] })),
91
+ text,
92
+ tagMap,
93
+ minScore
94
+ );
84
95
  }
85
96
  };
86
97
  }
@@ -20374,6 +20374,52 @@ async function getDecayCandidatesRawOp(ctx) {
20374
20374
  trustTier: raw.trust_tier ?? null
20375
20375
  }));
20376
20376
  }
20377
+ async function applyDecayTransitionsOp(ctx, candidates, opts) {
20378
+ assertVaultScopeForSweep(ctx);
20379
+ const byId = new Map(candidates.map((candidate) => [candidate.uniqueId, candidate]));
20380
+ const ids = Array.from(byId.keys());
20381
+ const changed = /* @__PURE__ */ new Set();
20382
+ const CHUNK = 500;
20383
+ for (let i = 0; i < ids.length; i += CHUNK) {
20384
+ let applied = [];
20385
+ try {
20386
+ await ctx.database.write(async () => {
20387
+ await assertCanWrite2(ctx);
20388
+ const records = await ctx.vaultMemoryCollection.query(
20389
+ import_watermelondb24.Q.where("id", import_watermelondb24.Q.oneOf(ids.slice(i, i + CHUNK))),
20390
+ ...ctx.userId !== void 0 ? [import_watermelondb24.Q.where("user_id", ctx.userId)] : []
20391
+ ).fetch();
20392
+ const eligible = records.filter((record2) => {
20393
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
20394
+ if (opts.transition === "delete") {
20395
+ return record2.archivedAt !== null && opts.now - record2.archivedAt > opts.hardDeleteWindowMs;
20396
+ }
20397
+ const candidate = byId.get(record2.id);
20398
+ return record2.archivedAt === null && record2.updatedAt.getTime() === candidate.updatedAt && (record2.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
20399
+ });
20400
+ const prepared = eligible.map(
20401
+ (record2) => record2.prepareUpdate((row) => {
20402
+ if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
20403
+ else row._setRaw("is_deleted", true);
20404
+ })
20405
+ );
20406
+ if (prepared.length > 0) await ctx.database.batch(prepared);
20407
+ applied = eligible.map((record2) => record2.id);
20408
+ });
20409
+ } catch {
20410
+ continue;
20411
+ }
20412
+ for (const id2 of applied) changed.add(id2);
20413
+ if (opts.transition === "delete" && ctx.entityCtx) {
20414
+ try {
20415
+ await unlinkMemoryEntitiesOp(ctx.entityCtx, applied);
20416
+ } catch {
20417
+ continue;
20418
+ }
20419
+ }
20420
+ }
20421
+ return changed;
20422
+ }
20377
20423
  async function archiveVaultMemoryOp(ctx, id2, opts) {
20378
20424
  try {
20379
20425
  const record2 = await ctx.vaultMemoryCollection.find(id2);
@@ -25444,25 +25490,8 @@ function isBorderline(input) {
25444
25490
  function vaultDecayBackend(vaultCtx) {
25445
25491
  return {
25446
25492
  candidates: () => getDecayCandidatesRawOp(vaultCtx),
25447
- archive: async (rows, now) => {
25448
- const archived = /* @__PURE__ */ new Set();
25449
- for (const c of rows) {
25450
- const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
25451
- now,
25452
- expectedUpdatedAt: c.updatedAt,
25453
- expectedLastObservedAt: c.lastObservedAt ?? null
25454
- });
25455
- if (ok) archived.add(c.uniqueId);
25456
- }
25457
- return archived;
25458
- },
25459
- hardDelete: async (rows, deleteOptions) => {
25460
- const deleted = /* @__PURE__ */ new Set();
25461
- for (const c of rows) {
25462
- if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
25463
- }
25464
- return deleted;
25465
- }
25493
+ archive: (rows, now) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "archive", now }),
25494
+ hardDelete: (rows, deleteOptions) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "delete", ...deleteOptions })
25466
25495
  };
25467
25496
  }
25468
25497
  function createDecaySweeper(options) {
@@ -27490,6 +27519,7 @@ function createLocalMemoryStore(options) {
27490
27519
  "trust_tier",
27491
27520
  "superseded_by",
27492
27521
  "visibility",
27522
+ "twin_opt_in",
27493
27523
  "published_at",
27494
27524
  "geohash",
27495
27525
  "topics",
@@ -28681,6 +28711,7 @@ function subscriptionState({ memory, version }) {
28681
28711
  memory.event_time_kind,
28682
28712
  memory.trust_tier,
28683
28713
  memory.visibility,
28714
+ memory.twin_opt_in,
28684
28715
  memory.published_at,
28685
28716
  memory.geohash,
28686
28717
  memory.topics,
@@ -18500,6 +18500,52 @@ async function getDecayCandidatesRawOp(ctx) {
18500
18500
  trustTier: raw.trust_tier ?? null
18501
18501
  }));
18502
18502
  }
18503
+ async function applyDecayTransitionsOp(ctx, candidates, opts) {
18504
+ assertVaultScopeForSweep(ctx);
18505
+ const byId = new Map(candidates.map((candidate) => [candidate.uniqueId, candidate]));
18506
+ const ids = Array.from(byId.keys());
18507
+ const changed = /* @__PURE__ */ new Set();
18508
+ const CHUNK = 500;
18509
+ for (let i = 0; i < ids.length; i += CHUNK) {
18510
+ let applied = [];
18511
+ try {
18512
+ await ctx.database.write(async () => {
18513
+ await assertCanWrite2(ctx);
18514
+ const records = await ctx.vaultMemoryCollection.query(
18515
+ Q9.where("id", Q9.oneOf(ids.slice(i, i + CHUNK))),
18516
+ ...ctx.userId !== void 0 ? [Q9.where("user_id", ctx.userId)] : []
18517
+ ).fetch();
18518
+ const eligible = records.filter((record2) => {
18519
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
18520
+ if (opts.transition === "delete") {
18521
+ return record2.archivedAt !== null && opts.now - record2.archivedAt > opts.hardDeleteWindowMs;
18522
+ }
18523
+ const candidate = byId.get(record2.id);
18524
+ return record2.archivedAt === null && record2.updatedAt.getTime() === candidate.updatedAt && (record2.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
18525
+ });
18526
+ const prepared = eligible.map(
18527
+ (record2) => record2.prepareUpdate((row) => {
18528
+ if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
18529
+ else row._setRaw("is_deleted", true);
18530
+ })
18531
+ );
18532
+ if (prepared.length > 0) await ctx.database.batch(prepared);
18533
+ applied = eligible.map((record2) => record2.id);
18534
+ });
18535
+ } catch {
18536
+ continue;
18537
+ }
18538
+ for (const id2 of applied) changed.add(id2);
18539
+ if (opts.transition === "delete" && ctx.entityCtx) {
18540
+ try {
18541
+ await unlinkMemoryEntitiesOp(ctx.entityCtx, applied);
18542
+ } catch {
18543
+ continue;
18544
+ }
18545
+ }
18546
+ }
18547
+ return changed;
18548
+ }
18503
18549
  async function archiveVaultMemoryOp(ctx, id2, opts) {
18504
18550
  try {
18505
18551
  const record2 = await ctx.vaultMemoryCollection.find(id2);
@@ -23536,25 +23582,8 @@ function isBorderline(input) {
23536
23582
  function vaultDecayBackend(vaultCtx) {
23537
23583
  return {
23538
23584
  candidates: () => getDecayCandidatesRawOp(vaultCtx),
23539
- archive: async (rows, now) => {
23540
- const archived = /* @__PURE__ */ new Set();
23541
- for (const c of rows) {
23542
- const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
23543
- now,
23544
- expectedUpdatedAt: c.updatedAt,
23545
- expectedLastObservedAt: c.lastObservedAt ?? null
23546
- });
23547
- if (ok) archived.add(c.uniqueId);
23548
- }
23549
- return archived;
23550
- },
23551
- hardDelete: async (rows, deleteOptions) => {
23552
- const deleted = /* @__PURE__ */ new Set();
23553
- for (const c of rows) {
23554
- if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
23555
- }
23556
- return deleted;
23557
- }
23585
+ archive: (rows, now) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "archive", now }),
23586
+ hardDelete: (rows, deleteOptions) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "delete", ...deleteOptions })
23558
23587
  };
23559
23588
  }
23560
23589
  function createDecaySweeper(options) {
@@ -25567,6 +25596,7 @@ function createLocalMemoryStore(options) {
25567
25596
  "trust_tier",
25568
25597
  "superseded_by",
25569
25598
  "visibility",
25599
+ "twin_opt_in",
25570
25600
  "published_at",
25571
25601
  "geohash",
25572
25602
  "topics",
@@ -26753,6 +26783,7 @@ function subscriptionState({ memory, version }) {
26753
26783
  memory.event_time_kind,
26754
26784
  memory.trust_tier,
26755
26785
  memory.visibility,
26786
+ memory.twin_opt_in,
26756
26787
  memory.published_at,
26757
26788
  memory.geohash,
26758
26789
  memory.topics,
@@ -29987,6 +29987,52 @@ async function getDecayCandidatesRawOp(ctx) {
29987
29987
  trustTier: raw.trust_tier ?? null
29988
29988
  }));
29989
29989
  }
29990
+ async function applyDecayTransitionsOp(ctx, candidates, opts) {
29991
+ assertVaultScopeForSweep(ctx);
29992
+ const byId = new Map(candidates.map((candidate) => [candidate.uniqueId, candidate]));
29993
+ const ids = Array.from(byId.keys());
29994
+ const changed = /* @__PURE__ */ new Set();
29995
+ const CHUNK = 500;
29996
+ for (let i = 0; i < ids.length; i += CHUNK) {
29997
+ let applied = [];
29998
+ try {
29999
+ await ctx.database.write(async () => {
30000
+ await assertCanWrite2(ctx);
30001
+ const records = await ctx.vaultMemoryCollection.query(
30002
+ import_watermelondb19.Q.where("id", import_watermelondb19.Q.oneOf(ids.slice(i, i + CHUNK))),
30003
+ ...ctx.userId !== void 0 ? [import_watermelondb19.Q.where("user_id", ctx.userId)] : []
30004
+ ).fetch();
30005
+ const eligible = records.filter((record) => {
30006
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
30007
+ if (opts.transition === "delete") {
30008
+ return record.archivedAt !== null && opts.now - record.archivedAt > opts.hardDeleteWindowMs;
30009
+ }
30010
+ const candidate = byId.get(record.id);
30011
+ return record.archivedAt === null && record.updatedAt.getTime() === candidate.updatedAt && (record.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
30012
+ });
30013
+ const prepared = eligible.map(
30014
+ (record) => record.prepareUpdate((row) => {
30015
+ if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
30016
+ else row._setRaw("is_deleted", true);
30017
+ })
30018
+ );
30019
+ if (prepared.length > 0) await ctx.database.batch(prepared);
30020
+ applied = eligible.map((record) => record.id);
30021
+ });
30022
+ } catch {
30023
+ continue;
30024
+ }
30025
+ for (const id of applied) changed.add(id);
30026
+ if (opts.transition === "delete" && ctx.entityCtx) {
30027
+ try {
30028
+ await unlinkMemoryEntitiesOp(ctx.entityCtx, applied);
30029
+ } catch {
30030
+ continue;
30031
+ }
30032
+ }
30033
+ }
30034
+ return changed;
30035
+ }
29990
30036
  async function archiveVaultMemoryOp(ctx, id, opts) {
29991
30037
  try {
29992
30038
  const record = await ctx.vaultMemoryCollection.find(id);
@@ -34752,25 +34798,8 @@ function isBorderline(input) {
34752
34798
  function vaultDecayBackend(vaultCtx) {
34753
34799
  return {
34754
34800
  candidates: () => getDecayCandidatesRawOp(vaultCtx),
34755
- archive: async (rows, now) => {
34756
- const archived = /* @__PURE__ */ new Set();
34757
- for (const c of rows) {
34758
- const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
34759
- now,
34760
- expectedUpdatedAt: c.updatedAt,
34761
- expectedLastObservedAt: c.lastObservedAt ?? null
34762
- });
34763
- if (ok) archived.add(c.uniqueId);
34764
- }
34765
- return archived;
34766
- },
34767
- hardDelete: async (rows, deleteOptions) => {
34768
- const deleted = /* @__PURE__ */ new Set();
34769
- for (const c of rows) {
34770
- if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
34771
- }
34772
- return deleted;
34773
- }
34801
+ archive: (rows, now) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "archive", now }),
34802
+ hardDelete: (rows, deleteOptions) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "delete", ...deleteOptions })
34774
34803
  };
34775
34804
  }
34776
34805
  function createDecaySweeper(options) {
@@ -36798,6 +36827,7 @@ function createLocalMemoryStore(options) {
36798
36827
  "trust_tier",
36799
36828
  "superseded_by",
36800
36829
  "visibility",
36830
+ "twin_opt_in",
36801
36831
  "published_at",
36802
36832
  "geohash",
36803
36833
  "topics",
@@ -28245,6 +28245,52 @@ async function getDecayCandidatesRawOp(ctx) {
28245
28245
  trustTier: raw.trust_tier ?? null
28246
28246
  }));
28247
28247
  }
28248
+ async function applyDecayTransitionsOp(ctx, candidates, opts) {
28249
+ assertVaultScopeForSweep(ctx);
28250
+ const byId = new Map(candidates.map((candidate) => [candidate.uniqueId, candidate]));
28251
+ const ids = Array.from(byId.keys());
28252
+ const changed = /* @__PURE__ */ new Set();
28253
+ const CHUNK = 500;
28254
+ for (let i = 0; i < ids.length; i += CHUNK) {
28255
+ let applied = [];
28256
+ try {
28257
+ await ctx.database.write(async () => {
28258
+ await assertCanWrite2(ctx);
28259
+ const records = await ctx.vaultMemoryCollection.query(
28260
+ import_watermelondb19.Q.where("id", import_watermelondb19.Q.oneOf(ids.slice(i, i + CHUNK))),
28261
+ ...ctx.userId !== void 0 ? [import_watermelondb19.Q.where("user_id", ctx.userId)] : []
28262
+ ).fetch();
28263
+ const eligible = records.filter((record) => {
28264
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
28265
+ if (opts.transition === "delete") {
28266
+ return record.archivedAt !== null && opts.now - record.archivedAt > opts.hardDeleteWindowMs;
28267
+ }
28268
+ const candidate = byId.get(record.id);
28269
+ return record.archivedAt === null && record.updatedAt.getTime() === candidate.updatedAt && (record.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
28270
+ });
28271
+ const prepared = eligible.map(
28272
+ (record) => record.prepareUpdate((row) => {
28273
+ if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
28274
+ else row._setRaw("is_deleted", true);
28275
+ })
28276
+ );
28277
+ if (prepared.length > 0) await ctx.database.batch(prepared);
28278
+ applied = eligible.map((record) => record.id);
28279
+ });
28280
+ } catch {
28281
+ continue;
28282
+ }
28283
+ for (const id of applied) changed.add(id);
28284
+ if (opts.transition === "delete" && ctx.entityCtx) {
28285
+ try {
28286
+ await unlinkMemoryEntitiesOp(ctx.entityCtx, applied);
28287
+ } catch {
28288
+ continue;
28289
+ }
28290
+ }
28291
+ }
28292
+ return changed;
28293
+ }
28248
28294
  async function archiveVaultMemoryOp(ctx, id, opts) {
28249
28295
  try {
28250
28296
  const record = await ctx.vaultMemoryCollection.find(id);
@@ -32982,25 +33028,8 @@ function isBorderline(input) {
32982
33028
  function vaultDecayBackend(vaultCtx) {
32983
33029
  return {
32984
33030
  candidates: () => getDecayCandidatesRawOp(vaultCtx),
32985
- archive: async (rows, now) => {
32986
- const archived = /* @__PURE__ */ new Set();
32987
- for (const c of rows) {
32988
- const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
32989
- now,
32990
- expectedUpdatedAt: c.updatedAt,
32991
- expectedLastObservedAt: c.lastObservedAt ?? null
32992
- });
32993
- if (ok) archived.add(c.uniqueId);
32994
- }
32995
- return archived;
32996
- },
32997
- hardDelete: async (rows, deleteOptions) => {
32998
- const deleted = /* @__PURE__ */ new Set();
32999
- for (const c of rows) {
33000
- if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
33001
- }
33002
- return deleted;
33003
- }
33031
+ archive: (rows, now) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "archive", now }),
33032
+ hardDelete: (rows, deleteOptions) => applyDecayTransitionsOp(vaultCtx, rows, { transition: "delete", ...deleteOptions })
33004
33033
  };
33005
33034
  }
33006
33035
  function createDecaySweeper(options) {
@@ -35013,6 +35042,7 @@ function createLocalMemoryStore(options) {
35013
35042
  "trust_tier",
35014
35043
  "superseded_by",
35015
35044
  "visibility",
35045
+ "twin_opt_in",
35016
35046
  "published_at",
35017
35047
  "geohash",
35018
35048
  "topics",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "10.6.0",
3
+ "version": "10.6.2",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",