@anuma/sdk 3.12.2 → 3.13.0

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.
@@ -1790,6 +1790,31 @@ var ENTITY_KINDS = [
1790
1790
  function normalizeEntityName(name) {
1791
1791
  return name.trim().toLowerCase();
1792
1792
  }
1793
+ function serializeTopics(topics) {
1794
+ return JSON.stringify(topics);
1795
+ }
1796
+ function parseTopics(value) {
1797
+ if (typeof value !== "string" || value.length === 0) return null;
1798
+ let parsed;
1799
+ try {
1800
+ parsed = JSON.parse(value);
1801
+ } catch {
1802
+ return null;
1803
+ }
1804
+ if (!Array.isArray(parsed)) return null;
1805
+ const out = [];
1806
+ for (const raw of parsed) {
1807
+ if (typeof raw !== "object" || raw === null) continue;
1808
+ const { name, kind, source } = raw;
1809
+ if (typeof name !== "string" || name.trim().length === 0) continue;
1810
+ out.push({
1811
+ name,
1812
+ ...typeof kind === "string" && kind.length > 0 ? { kind } : {},
1813
+ source: source === "user" ? "user" : "auto"
1814
+ });
1815
+ }
1816
+ return out;
1817
+ }
1793
1818
 
1794
1819
  // src/lib/db/entities/operations.ts
1795
1820
  function entityToStored(e) {
@@ -1839,9 +1864,62 @@ async function upsertEntitiesInWrite(ctx, entities) {
1839
1864
  for (const record of created) out.set(record.canonicalName, entityToStored(record));
1840
1865
  return { entities: out, operations: [...created, ...updated] };
1841
1866
  }
1867
+ async function findVaultRowInWrite(ctx, memoryId) {
1868
+ try {
1869
+ const rows = await ctx.database.get("memory_vault").query(Q2.where("id", memoryId)).fetch();
1870
+ return rows[0] ?? null;
1871
+ } catch {
1872
+ return null;
1873
+ }
1874
+ }
1875
+ function prepareTopicsUpdate(row, topics, now) {
1876
+ const originalUpdatedAt = row.updatedAt.getTime();
1877
+ return row.prepareUpdate((r) => {
1878
+ r._setRaw("topics", serializeTopics(topics));
1879
+ r._setRaw("topics_updated_at", now);
1880
+ r._setRaw("updated_at", originalUpdatedAt);
1881
+ });
1882
+ }
1883
+ function displayNamesOf(entities) {
1884
+ const out = /* @__PURE__ */ new Map();
1885
+ for (const e of entities) {
1886
+ const name = e.name.trim();
1887
+ const normalized = normalizeEntityName(name);
1888
+ if (normalized.length === 0 || out.has(normalized)) continue;
1889
+ out.set(normalized, name);
1890
+ }
1891
+ return out;
1892
+ }
1893
+ function topicsEqual(stored, computed) {
1894
+ if (stored === null || stored.length !== computed.length) return false;
1895
+ const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
1896
+ const storedKeys = stored.map(key).sort();
1897
+ const computedKeys = computed.map(key).sort();
1898
+ return storedKeys.every((k, i) => k === computedKeys[i]);
1899
+ }
1900
+ function resolveTopicsWrite(row, linked, displayNames, source) {
1901
+ if (row === null || source === null) return null;
1902
+ const topics = topicsForEntities(linked, displayNames, source);
1903
+ if (topicsEqual(parseTopics(row.topics), topics)) return null;
1904
+ return { row, topics };
1905
+ }
1906
+ function topicsForEntities(entities, displayNames, source) {
1907
+ return entities.map((e) => {
1908
+ const name = displayNames.get(e.canonicalName) ?? e.canonicalName;
1909
+ return { name, ...e.kind ? { kind: e.kind } : {}, source };
1910
+ });
1911
+ }
1912
+ function toEntityObjects(entityInputs) {
1913
+ return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
1914
+ }
1915
+ async function prepareMemoryTopicsUpdate(ctx, memoryId, linked, inputs, source) {
1916
+ const row = await findVaultRowInWrite(ctx, memoryId);
1917
+ const write = resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
1918
+ return write === null ? null : prepareTopicsUpdate(write.row, write.topics, Date.now());
1919
+ }
1842
1920
  async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
1843
1921
  if (entityInputs.length === 0) return [];
1844
- const normalized = entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
1922
+ const normalized = toEntityObjects(entityInputs);
1845
1923
  const userId = ctx.userId;
1846
1924
  let skipped = false;
1847
1925
  let entities = [];
@@ -1851,7 +1929,8 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
1851
1929
  normalized
1852
1930
  );
1853
1931
  entities = Array.from(byName.values());
1854
- if (options?.unlessTopicsUserManaged && await autoLinkBlocked(ctx, memoryId)) {
1932
+ const vaultRow = await findVaultRowInWrite(ctx, memoryId);
1933
+ if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
1855
1934
  if (entityOps.length > 0) {
1856
1935
  await ctx.database.batch(...entityOps);
1857
1936
  }
@@ -1862,7 +1941,18 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
1862
1941
  const existingLinks = await ctx.memoryEntityCollection.query(Q2.where("memory_id", memoryId)).fetch();
1863
1942
  const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
1864
1943
  const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
1865
- if (entityOps.length === 0 && toCreate.length === 0) return;
1944
+ const keptIds = entities.map((e) => e.uniqueId);
1945
+ const carriedOver = await resolveEntitiesByIds(
1946
+ ctx,
1947
+ [...existingEntityIds].filter((id) => !keptIds.includes(id))
1948
+ );
1949
+ const topicsWrite = resolveTopicsWrite(
1950
+ vaultRow,
1951
+ [...carriedOver, ...entities],
1952
+ displayNamesOf(normalized),
1953
+ options?.topicsSource ?? "auto"
1954
+ );
1955
+ if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null) return;
1866
1956
  const linkOps = toCreate.map(
1867
1957
  (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
1868
1958
  record._setRaw("memory_id", memoryId);
@@ -1870,26 +1960,42 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
1870
1960
  if (userId !== void 0) record._setRaw("user_id", userId);
1871
1961
  })
1872
1962
  );
1873
- await ctx.database.batch(...entityOps, ...linkOps);
1963
+ await ctx.database.batch(
1964
+ ...entityOps,
1965
+ ...linkOps,
1966
+ ...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
1967
+ );
1874
1968
  });
1875
1969
  return skipped ? [] : entities;
1876
1970
  }
1877
- async function autoLinkBlocked(ctx, memoryId) {
1878
- try {
1879
- const rows = await ctx.database.get("memory_vault").query(Q2.where("id", memoryId)).fetch();
1880
- const row = rows[0];
1881
- return !row || !!row.isDeleted || !!row.topicsUserManaged;
1882
- } catch {
1883
- return true;
1884
- }
1971
+ async function resolveEntitiesByIds(ctx, entityIds) {
1972
+ if (entityIds.length === 0) return [];
1973
+ const rows = await ctx.entityCollection.query(Q2.where("id", Q2.oneOf(Array.from(entityIds)))).fetch();
1974
+ return rows.map(entityToStored);
1975
+ }
1976
+ function autoLinkBlocked(row) {
1977
+ return !row || !!row.isDeleted || !!row.topicsUserManaged;
1885
1978
  }
1886
1979
  async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
1887
- const normalized = entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
1980
+ return replaceMemoryEntities(ctx, memoryId, entityInputs, {
1981
+ guarded: true,
1982
+ topicsSource: "auto"
1983
+ });
1984
+ }
1985
+ async function relinkMemoryEntitiesFromTopicsOp(ctx, memoryId, topics) {
1986
+ return replaceMemoryEntities(ctx, memoryId, topics, {
1987
+ guarded: false,
1988
+ topicsSource: null
1989
+ });
1990
+ }
1991
+ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
1992
+ const normalized = toEntityObjects(entityInputs);
1888
1993
  const userId = ctx.userId;
1889
1994
  let skipped = false;
1890
1995
  let entities = [];
1891
1996
  await ctx.database.write(async () => {
1892
- if (await autoLinkBlocked(ctx, memoryId)) {
1997
+ const vaultRow = await findVaultRowInWrite(ctx, memoryId);
1998
+ if (options.guarded && autoLinkBlocked(vaultRow)) {
1893
1999
  skipped = true;
1894
2000
  return;
1895
2001
  }
@@ -1903,7 +2009,15 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
1903
2009
  const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
1904
2010
  const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
1905
2011
  const toDestroy = existingLinks.filter((l) => !keep.has(String(l.entityId)));
1906
- if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0) return;
2012
+ const topicsWrite = resolveTopicsWrite(
2013
+ vaultRow,
2014
+ entities,
2015
+ displayNamesOf(normalized),
2016
+ options.topicsSource
2017
+ );
2018
+ if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
2019
+ return;
2020
+ }
1907
2021
  const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
1908
2022
  await ctx.database.batch(
1909
2023
  ...entityOps,
@@ -1915,7 +2029,8 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
1915
2029
  })
1916
2030
  ),
1917
2031
  ...toDestroy.map((l) => l.prepareDestroyPermanently()),
1918
- ...orphans.map((e) => e.prepareDestroyPermanently())
2032
+ ...orphans.map((e) => e.prepareDestroyPermanently()),
2033
+ ...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
1919
2034
  );
1920
2035
  });
1921
2036
  return skipped ? null : entities;
@@ -2103,6 +2218,8 @@ function vaultMemoryToStoredRaw(memory) {
2103
2218
  eventTimeEnd: memory.eventTimeEnd ?? null,
2104
2219
  eventTimeKind: memory.eventTimeKind ?? null,
2105
2220
  topicsUserManaged: memory.topicsUserManaged ?? false,
2221
+ topics: parseTopics(memory.topics),
2222
+ topicsUpdatedAt: memory.topicsUpdatedAt ?? null,
2106
2223
  topicsExtractedAt: memory.topicsExtractedAt ?? null,
2107
2224
  topicsExtractedVersion: memory.topicsExtractedVersion ?? null,
2108
2225
  supersededBy: memory.supersededBy ?? null,
@@ -2379,6 +2496,8 @@ function vaultMemoryRawToStoredRaw(raw) {
2379
2496
  eventTimeKind: raw.event_time_kind ?? null,
2380
2497
  // SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
2381
2498
  topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
2499
+ topics: parseTopics(raw.topics),
2500
+ topicsUpdatedAt: raw.topics_updated_at ?? null,
2382
2501
  topicsExtractedAt: raw.topics_extracted_at ?? null,
2383
2502
  topicsExtractedVersion: raw.topics_extracted_version ?? null,
2384
2503
  supersededBy: raw.superseded_by ?? null,
@@ -2726,56 +2845,111 @@ async function getUnfiledVaultMemoriesOp(ctx) {
2726
2845
  );
2727
2846
  }
2728
2847
  var TOPICS_EXTRACTION_VERSION = 3;
2848
+ async function linkedEntityNamesByMemory(entityCtx, memoryIds) {
2849
+ const CHUNK = 500;
2850
+ const entityIdByMemory = /* @__PURE__ */ new Map();
2851
+ const allEntityIds = /* @__PURE__ */ new Set();
2852
+ for (let i = 0; i < memoryIds.length; i += CHUNK) {
2853
+ const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", Q3.oneOf(memoryIds.slice(i, i + CHUNK)))).unsafeFetchRaw();
2854
+ for (const link of links) {
2855
+ const memoryId = String(link.memory_id);
2856
+ const entityId = String(link.entity_id);
2857
+ allEntityIds.add(entityId);
2858
+ let bucket = entityIdByMemory.get(memoryId);
2859
+ if (!bucket) {
2860
+ bucket = /* @__PURE__ */ new Set();
2861
+ entityIdByMemory.set(memoryId, bucket);
2862
+ }
2863
+ bucket.add(entityId);
2864
+ }
2865
+ }
2866
+ const entityIds = Array.from(allEntityIds);
2867
+ const nameById = /* @__PURE__ */ new Map();
2868
+ for (let i = 0; i < entityIds.length; i += CHUNK) {
2869
+ const entities = await entityCtx.entityCollection.query(Q3.where("id", Q3.oneOf(entityIds.slice(i, i + CHUNK)))).unsafeFetchRaw();
2870
+ for (const e of entities) {
2871
+ if (typeof e.canonical_name === "string") nameById.set(String(e.id), e.canonical_name);
2872
+ }
2873
+ }
2874
+ const out = /* @__PURE__ */ new Map();
2875
+ for (const [memoryId, ids] of entityIdByMemory) {
2876
+ const names = /* @__PURE__ */ new Set();
2877
+ for (const id of ids) {
2878
+ const name = nameById.get(id);
2879
+ if (name !== void 0) names.add(name);
2880
+ }
2881
+ if (names.size > 0) out.set(memoryId, names);
2882
+ }
2883
+ return out;
2884
+ }
2885
+ function linksDivergeFromTopics(topics, linked) {
2886
+ const wanted = new Set(
2887
+ topics.map((t) => normalizeEntityName(t.name)).filter((n) => n.length > 0)
2888
+ );
2889
+ if (wanted.size !== linked.size) return true;
2890
+ for (const name of wanted) if (!linked.has(name)) return true;
2891
+ return false;
2892
+ }
2729
2893
  async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
2730
2894
  const entityCtx = ctx.entityCtx;
2731
2895
  if (!entityCtx) {
2732
2896
  throw new Error("getMemoriesNeedingTopicExtractionOp requires ctx.entityCtx");
2733
2897
  }
2734
- const conditions = [
2735
- // Boolean optional column: null (legacy) and false both mean auto-managed.
2736
- // Q.notEq(true) is a NULL trap on SQLite (NULL <> TRUE is NULL) — enumerate.
2737
- Q3.or(Q3.where("topics_user_managed", null), Q3.where("topics_user_managed", false)),
2738
- ...baseVaultConditions(ctx),
2739
- Q3.sortBy("created_at", Q3.desc)
2740
- ];
2898
+ const conditions = [...baseVaultConditions(ctx), Q3.sortBy("created_at", Q3.desc)];
2741
2899
  const rows = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
2742
- const stampedPending = [];
2743
- const unstamped = [];
2900
+ const linkedNames = await linkedEntityNamesByMemory(
2901
+ entityCtx,
2902
+ rows.map((r) => r.id)
2903
+ );
2904
+ const pendingRaw = [];
2905
+ const stampedPendingRaw = [];
2906
+ const linkedUnstampedAll = [];
2907
+ const topicsToRelinkAll = [];
2908
+ const topicsBackfillAll = [];
2744
2909
  for (const raw of rows) {
2910
+ const id = raw.id;
2911
+ const topics = parseTopics(raw.topics);
2912
+ const linked = linkedNames.get(id);
2913
+ if (topics !== null && topics.length > 0 && linksDivergeFromTopics(topics, linked ?? /* @__PURE__ */ new Set())) {
2914
+ topicsToRelinkAll.push(id);
2915
+ continue;
2916
+ }
2917
+ if (raw.topics_user_managed) {
2918
+ if (topics === null && linked !== void 0) topicsBackfillAll.push(id);
2919
+ continue;
2920
+ }
2745
2921
  const stamp = raw.topics_extracted_at ?? null;
2922
+ let isPending = false;
2746
2923
  if (stamp !== null) {
2747
2924
  const version = raw.topics_extracted_version ?? 0;
2748
2925
  if (raw.updated_at > stamp || version < TOPICS_EXTRACTION_VERSION) {
2749
- stampedPending.push(raw);
2926
+ stampedPendingRaw.push(raw);
2927
+ isPending = true;
2750
2928
  }
2751
- } else {
2752
- unstamped.push(raw);
2753
- }
2754
- }
2755
- const linkedIds = /* @__PURE__ */ new Set();
2756
- const CHUNK = 500;
2757
- for (let i = 0; i < unstamped.length; i += CHUNK) {
2758
- const ids = unstamped.slice(i, i + CHUNK).map((r) => r.id);
2759
- const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", Q3.oneOf(ids))).unsafeFetchRaw();
2760
- for (const link of links) linkedIds.add(String(link.memory_id));
2761
- }
2762
- const linkedUnstampedAll = [];
2763
- const pendingRaw = [...stampedPending];
2764
- for (const raw of unstamped) {
2765
- if (linkedIds.has(raw.id)) {
2766
- linkedUnstampedAll.push(raw.id);
2929
+ } else if (linked !== void 0) {
2930
+ linkedUnstampedAll.push(id);
2767
2931
  } else {
2768
2932
  pendingRaw.push(raw);
2933
+ isPending = true;
2934
+ }
2935
+ if (!isPending && topics === null && linked !== void 0) {
2936
+ topicsBackfillAll.push(id);
2769
2937
  }
2770
2938
  }
2771
2939
  const cap = options?.limit !== void 0 && options.limit > 0 ? options.limit : void 0;
2772
- const limitedPendingRaw = cap !== void 0 ? pendingRaw.slice(0, cap) : pendingRaw;
2773
- const linkedUnstamped = cap !== void 0 ? linkedUnstampedAll.slice(0, cap) : linkedUnstampedAll;
2940
+ const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
2941
+ const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
2774
2942
  const pending = await mapInBatches(
2775
2943
  limitedPendingRaw,
2776
2944
  (raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
2777
2945
  );
2778
- return { pending, linkedUnstamped };
2946
+ const applyCap = (ids) => cap !== void 0 ? ids.slice(0, cap) : ids;
2947
+ return {
2948
+ pending,
2949
+ linkedUnstamped: applyCap(linkedUnstampedAll),
2950
+ topicsToRelink: applyCap(topicsToRelinkAll),
2951
+ topicsBackfill: applyCap(topicsBackfillAll)
2952
+ };
2779
2953
  }
2780
2954
  async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) {
2781
2955
  if (memoryIds.length === 0) return [];
@@ -2809,6 +2983,61 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
2809
2983
  }
2810
2984
  return stamped;
2811
2985
  }
2986
+ async function relinkMemoryTopicsOp(ctx, memoryIds) {
2987
+ const entityCtx = ctx.entityCtx;
2988
+ if (!entityCtx) {
2989
+ throw new Error("relinkMemoryTopicsOp requires ctx.entityCtx");
2990
+ }
2991
+ const relinked = [];
2992
+ for (const id of Array.from(new Set(memoryIds))) {
2993
+ let record;
2994
+ try {
2995
+ record = await ctx.vaultMemoryCollection.find(id);
2996
+ } catch {
2997
+ continue;
2998
+ }
2999
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
3000
+ const topics = parseTopics(record.topics);
3001
+ if (topics === null || topics.length === 0) continue;
3002
+ try {
3003
+ await relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics);
3004
+ relinked.push(id);
3005
+ } catch (err) {
3006
+ getLogger().warn("[memory/topics] relink failed", err);
3007
+ }
3008
+ }
3009
+ return relinked;
3010
+ }
3011
+ async function backfillMemoryTopicsOp(ctx, memoryIds) {
3012
+ const entityCtx = ctx.entityCtx;
3013
+ if (!entityCtx) {
3014
+ throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
3015
+ }
3016
+ const filled = [];
3017
+ for (const id of Array.from(new Set(memoryIds))) {
3018
+ let record;
3019
+ try {
3020
+ record = await ctx.vaultMemoryCollection.find(id);
3021
+ } catch {
3022
+ continue;
3023
+ }
3024
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
3025
+ if (parseTopics(record.topics) !== null) continue;
3026
+ const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", id)).unsafeFetchRaw();
3027
+ const entityIds = links.map((l) => String(l.entity_id));
3028
+ if (entityIds.length === 0) continue;
3029
+ const entities = await entityCtx.entityCollection.query(Q3.where("id", Q3.oneOf(entityIds))).fetch();
3030
+ if (entities.length === 0) continue;
3031
+ const source = record.topicsUserManaged ? "user" : "auto";
3032
+ await ctx.database.write(async () => {
3033
+ const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, id, entities, [], source);
3034
+ if (!topicsOp) return;
3035
+ await ctx.database.batch(topicsOp);
3036
+ filled.push(id);
3037
+ });
3038
+ }
3039
+ return filled;
3040
+ }
2812
3041
  async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
2813
3042
  if (ctx.userId !== void 0 && ctx.userId !== userId) return 0;
2814
3043
  const records = await ctx.vaultMemoryCollection.query(Q3.where("user_id", userId), Q3.where("is_deleted", false)).fetch();
@@ -5890,7 +6119,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
5890
6119
  legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
5891
6120
  );
5892
6121
  }
5893
- const { recall: recall2 } = await import("./recall-A4WZELH5.mjs");
6122
+ const { recall: recall2 } = await import("./recall-O65PGPIQ.mjs");
5894
6123
  let recallDegraded = [];
5895
6124
  const result = await recall2(
5896
6125
  query,
@@ -6911,6 +7140,8 @@ export {
6911
7140
  TOPICS_EXTRACTION_VERSION,
6912
7141
  getMemoriesNeedingTopicExtractionOp,
6913
7142
  stampTopicsExtractedAtOp,
7143
+ relinkMemoryTopicsOp,
7144
+ backfillMemoryTopicsOp,
6914
7145
  deleteAllVaultMemoriesForUserOp,
6915
7146
  assertVaultScopeForSweep,
6916
7147
  getDecayCandidatesRawOp,