@anuma/sdk 6.8.2 → 6.10.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.
@@ -2175,13 +2175,13 @@ async function upsertEntitiesInWrite(ctx, entities) {
2175
2175
  }
2176
2176
  const unique = Array.from(kindByName.keys());
2177
2177
  const out = /* @__PURE__ */ new Map();
2178
- if (unique.length === 0) return { entities: out, operations: [] };
2178
+ if (unique.length === 0) return { entities: out, operations: [], kindBackfills: [] };
2179
2179
  const existing = await ctx.entityCollection.query(Q2.where("canonical_name", Q2.oneOf(unique))).fetch();
2180
2180
  const existingNames = new Set(existing.map((e) => e.canonicalName));
2181
- const updates = existing.filter((e) => {
2181
+ const kindBackfills = existing.filter((e) => {
2182
2182
  const incoming = kindByName.get(e.canonicalName);
2183
2183
  return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
2184
- });
2184
+ }).map((record) => ({ record, kind: kindByName.get(record.canonicalName) }));
2185
2185
  const missing = unique.filter((n) => !existingNames.has(n));
2186
2186
  const created = missing.map(
2187
2187
  (name) => ctx.entityCollection.prepareCreate((record) => {
@@ -2190,14 +2190,19 @@ async function upsertEntitiesInWrite(ctx, entities) {
2190
2190
  if (kind !== void 0) record._setRaw("kind", kind);
2191
2191
  })
2192
2192
  );
2193
- const updated = updates.map(
2194
- (e) => e.prepareUpdate((record) => {
2195
- record._setRaw("kind", kindByName.get(e.canonicalName));
2196
- })
2197
- );
2198
2193
  for (const e of existing) out.set(e.canonicalName, entityToStored(e));
2199
2194
  for (const record of created) out.set(record.canonicalName, entityToStored(record));
2200
- return { entities: out, operations: [...created, ...updated] };
2195
+ for (const { record, kind } of kindBackfills) {
2196
+ out.set(record.canonicalName, { ...entityToStored(record), kind });
2197
+ }
2198
+ return { entities: out, operations: created, kindBackfills };
2199
+ }
2200
+ function prepareKindBackfills(backfills) {
2201
+ return backfills.map(
2202
+ ({ record, kind }) => record.prepareUpdate((r) => {
2203
+ r._setRaw("kind", kind);
2204
+ })
2205
+ );
2201
2206
  }
2202
2207
  async function findVaultRowInWrite(ctx, memoryId) {
2203
2208
  try {
@@ -2247,10 +2252,12 @@ function topicsForEntities(entities, displayNames, source) {
2247
2252
  function toEntityObjects(entityInputs) {
2248
2253
  return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
2249
2254
  }
2250
- async function prepareMemoryTopicsUpdate(ctx, memoryId, linked, inputs, source) {
2255
+ async function resolveMemoryTopicsWrite(ctx, memoryId, linked, inputs, source) {
2251
2256
  const row = await findVaultRowInWrite(ctx, memoryId);
2252
- const write = resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
2253
- return write === null ? null : prepareTopicsUpdate(write.row, write.topics, Date.now());
2257
+ return resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
2258
+ }
2259
+ function prepareMemoryTopicsUpdate(write) {
2260
+ return prepareTopicsUpdate(write.row, write.topics, Date.now());
2254
2261
  }
2255
2262
  async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
2256
2263
  if (entityInputs.length === 0) return [];
@@ -2259,15 +2266,16 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
2259
2266
  let skipped = false;
2260
2267
  let entities = [];
2261
2268
  await ctx.database.write(async () => {
2262
- const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
2263
- ctx,
2264
- normalized
2265
- );
2269
+ const {
2270
+ entities: byName,
2271
+ operations: entityOps,
2272
+ kindBackfills
2273
+ } = await upsertEntitiesInWrite(ctx, normalized);
2266
2274
  entities = Array.from(byName.values());
2267
2275
  const vaultRow = await findVaultRowInWrite(ctx, memoryId);
2268
2276
  if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
2269
- if (entityOps.length > 0) {
2270
- await ctx.database.batch(...entityOps);
2277
+ if (entityOps.length > 0 || kindBackfills.length > 0) {
2278
+ await ctx.database.batch(...entityOps, ...prepareKindBackfills(kindBackfills));
2271
2279
  }
2272
2280
  skipped = true;
2273
2281
  return;
@@ -2287,7 +2295,9 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
2287
2295
  displayNamesOf(normalized),
2288
2296
  options?.topicsSource ?? "auto"
2289
2297
  );
2290
- if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null) return;
2298
+ if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && topicsWrite === null) {
2299
+ return;
2300
+ }
2291
2301
  const linkOps = toCreate.map(
2292
2302
  (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
2293
2303
  record._setRaw("memory_id", memoryId);
@@ -2297,6 +2307,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
2297
2307
  );
2298
2308
  await ctx.database.batch(
2299
2309
  ...entityOps,
2310
+ ...prepareKindBackfills(kindBackfills),
2300
2311
  ...linkOps,
2301
2312
  ...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
2302
2313
  );
@@ -2334,10 +2345,11 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
2334
2345
  skipped = true;
2335
2346
  return;
2336
2347
  }
2337
- const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
2338
- ctx,
2339
- normalized
2340
- );
2348
+ const {
2349
+ entities: byName,
2350
+ operations: entityOps,
2351
+ kindBackfills
2352
+ } = await upsertEntitiesInWrite(ctx, normalized);
2341
2353
  entities = Array.from(byName.values());
2342
2354
  const existingLinks = await ctx.memoryEntityCollection.query(Q2.where("memory_id", memoryId)).fetch();
2343
2355
  const keep = new Set(entities.map((e) => e.uniqueId));
@@ -2350,12 +2362,13 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
2350
2362
  displayNamesOf(normalized),
2351
2363
  options.topicsSource
2352
2364
  );
2353
- if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
2365
+ if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
2354
2366
  return;
2355
2367
  }
2356
2368
  const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
2357
2369
  await ctx.database.batch(
2358
2370
  ...entityOps,
2371
+ ...prepareKindBackfills(kindBackfills),
2359
2372
  ...toCreate.map(
2360
2373
  (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
2361
2374
  record._setRaw("memory_id", memoryId);
@@ -3429,27 +3442,36 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
3429
3442
  if (!entityCtx) {
3430
3443
  throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
3431
3444
  }
3445
+ const uniqueIds = Array.from(new Set(memoryIds));
3446
+ if (uniqueIds.length === 0) return [];
3432
3447
  const filled = [];
3433
- for (const id of Array.from(new Set(memoryIds))) {
3434
- let record;
3435
- try {
3436
- record = await ctx.vaultMemoryCollection.find(id);
3437
- } catch {
3438
- continue;
3439
- }
3440
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
3441
- if (parseTopics(record.topics) !== null) continue;
3442
- const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", id)).unsafeFetchRaw();
3443
- const entityIds = links.map((l) => String(l.entity_id));
3444
- if (entityIds.length === 0) continue;
3445
- const entities = await entityCtx.entityCollection.query(Q3.where("id", Q3.oneOf(entityIds))).fetch();
3446
- if (entities.length === 0) continue;
3447
- const source = record.topicsUserManaged ? "user" : "auto";
3448
+ const CHUNK = 500;
3449
+ for (let i = 0; i < uniqueIds.length; i += CHUNK) {
3450
+ const chunkIds = uniqueIds.slice(i, i + CHUNK);
3448
3451
  await ctx.database.write(async () => {
3449
- const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, id, entities, [], source);
3450
- if (!topicsOp) return;
3451
- await ctx.database.batch(topicsOp);
3452
- filled.push(id);
3452
+ const writes = [];
3453
+ for (const id of chunkIds) {
3454
+ let record;
3455
+ try {
3456
+ record = await ctx.vaultMemoryCollection.find(id);
3457
+ } catch {
3458
+ continue;
3459
+ }
3460
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
3461
+ if (parseTopics(record.topics) !== null) continue;
3462
+ const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", id)).unsafeFetchRaw();
3463
+ const entityIds = links.map((l) => String(l.entity_id));
3464
+ if (entityIds.length === 0) continue;
3465
+ const entities = await entityCtx.entityCollection.query(Q3.where("id", Q3.oneOf(entityIds))).fetch();
3466
+ if (entities.length === 0) continue;
3467
+ const source = record.topicsUserManaged ? "user" : "auto";
3468
+ const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
3469
+ if (write) writes.push(write);
3470
+ }
3471
+ if (writes.length === 0) return;
3472
+ const prepared = writes.map(prepareMemoryTopicsUpdate);
3473
+ await ctx.database.batch(...prepared);
3474
+ for (const write of writes) filled.push(write.row.id);
3453
3475
  });
3454
3476
  }
3455
3477
  return filled;
@@ -6818,7 +6840,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
6818
6840
  subQueries = decomp.subQueries;
6819
6841
  }
6820
6842
  }
6821
- const { recall: recall2 } = await import("./recall-77QK4RT6.mjs");
6843
+ const { recall: recall2 } = await import("./recall-WIB7RQQZ.mjs");
6822
6844
  let recallDegraded = [];
6823
6845
  const result = await recall2(
6824
6846
  query,
@@ -4671,13 +4671,13 @@ async function upsertEntitiesInWrite(ctx, entities) {
4671
4671
  }
4672
4672
  const unique = Array.from(kindByName.keys());
4673
4673
  const out = /* @__PURE__ */ new Map();
4674
- if (unique.length === 0) return { entities: out, operations: [] };
4674
+ if (unique.length === 0) return { entities: out, operations: [], kindBackfills: [] };
4675
4675
  const existing = await ctx.entityCollection.query(import_watermelondb8.Q.where("canonical_name", import_watermelondb8.Q.oneOf(unique))).fetch();
4676
4676
  const existingNames = new Set(existing.map((e) => e.canonicalName));
4677
- const updates = existing.filter((e) => {
4677
+ const kindBackfills = existing.filter((e) => {
4678
4678
  const incoming = kindByName.get(e.canonicalName);
4679
4679
  return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
4680
- });
4680
+ }).map((record) => ({ record, kind: kindByName.get(record.canonicalName) }));
4681
4681
  const missing = unique.filter((n) => !existingNames.has(n));
4682
4682
  const created = missing.map(
4683
4683
  (name) => ctx.entityCollection.prepareCreate((record) => {
@@ -4686,14 +4686,19 @@ async function upsertEntitiesInWrite(ctx, entities) {
4686
4686
  if (kind !== void 0) record._setRaw("kind", kind);
4687
4687
  })
4688
4688
  );
4689
- const updated = updates.map(
4690
- (e) => e.prepareUpdate((record) => {
4691
- record._setRaw("kind", kindByName.get(e.canonicalName));
4692
- })
4693
- );
4694
4689
  for (const e of existing) out.set(e.canonicalName, entityToStored(e));
4695
4690
  for (const record of created) out.set(record.canonicalName, entityToStored(record));
4696
- return { entities: out, operations: [...created, ...updated] };
4691
+ for (const { record, kind } of kindBackfills) {
4692
+ out.set(record.canonicalName, { ...entityToStored(record), kind });
4693
+ }
4694
+ return { entities: out, operations: created, kindBackfills };
4695
+ }
4696
+ function prepareKindBackfills(backfills) {
4697
+ return backfills.map(
4698
+ ({ record, kind }) => record.prepareUpdate((r) => {
4699
+ r._setRaw("kind", kind);
4700
+ })
4701
+ );
4697
4702
  }
4698
4703
  async function findVaultRowInWrite(ctx, memoryId) {
4699
4704
  try {
@@ -4743,10 +4748,12 @@ function topicsForEntities(entities, displayNames, source) {
4743
4748
  function toEntityObjects(entityInputs) {
4744
4749
  return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
4745
4750
  }
4746
- async function prepareMemoryTopicsUpdate(ctx, memoryId, linked, inputs, source) {
4751
+ async function resolveMemoryTopicsWrite(ctx, memoryId, linked, inputs, source) {
4747
4752
  const row = await findVaultRowInWrite(ctx, memoryId);
4748
- const write = resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
4749
- return write === null ? null : prepareTopicsUpdate(write.row, write.topics, Date.now());
4753
+ return resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
4754
+ }
4755
+ function prepareMemoryTopicsUpdate(write) {
4756
+ return prepareTopicsUpdate(write.row, write.topics, Date.now());
4750
4757
  }
4751
4758
  async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
4752
4759
  if (entityInputs.length === 0) return [];
@@ -4755,15 +4762,16 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
4755
4762
  let skipped = false;
4756
4763
  let entities = [];
4757
4764
  await ctx.database.write(async () => {
4758
- const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
4759
- ctx,
4760
- normalized
4761
- );
4765
+ const {
4766
+ entities: byName,
4767
+ operations: entityOps,
4768
+ kindBackfills
4769
+ } = await upsertEntitiesInWrite(ctx, normalized);
4762
4770
  entities = Array.from(byName.values());
4763
4771
  const vaultRow = await findVaultRowInWrite(ctx, memoryId);
4764
4772
  if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
4765
- if (entityOps.length > 0) {
4766
- await ctx.database.batch(...entityOps);
4773
+ if (entityOps.length > 0 || kindBackfills.length > 0) {
4774
+ await ctx.database.batch(...entityOps, ...prepareKindBackfills(kindBackfills));
4767
4775
  }
4768
4776
  skipped = true;
4769
4777
  return;
@@ -4783,7 +4791,9 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
4783
4791
  displayNamesOf(normalized),
4784
4792
  options?.topicsSource ?? "auto"
4785
4793
  );
4786
- if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null) return;
4794
+ if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && topicsWrite === null) {
4795
+ return;
4796
+ }
4787
4797
  const linkOps = toCreate.map(
4788
4798
  (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
4789
4799
  record._setRaw("memory_id", memoryId);
@@ -4793,6 +4803,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
4793
4803
  );
4794
4804
  await ctx.database.batch(
4795
4805
  ...entityOps,
4806
+ ...prepareKindBackfills(kindBackfills),
4796
4807
  ...linkOps,
4797
4808
  ...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
4798
4809
  );
@@ -4830,10 +4841,11 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
4830
4841
  skipped = true;
4831
4842
  return;
4832
4843
  }
4833
- const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
4834
- ctx,
4835
- normalized
4836
- );
4844
+ const {
4845
+ entities: byName,
4846
+ operations: entityOps,
4847
+ kindBackfills
4848
+ } = await upsertEntitiesInWrite(ctx, normalized);
4837
4849
  entities = Array.from(byName.values());
4838
4850
  const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb8.Q.where("memory_id", memoryId)).fetch();
4839
4851
  const keep = new Set(entities.map((e) => e.uniqueId));
@@ -4846,12 +4858,13 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
4846
4858
  displayNamesOf(normalized),
4847
4859
  options.topicsSource
4848
4860
  );
4849
- if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
4861
+ if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
4850
4862
  return;
4851
4863
  }
4852
4864
  const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
4853
4865
  await ctx.database.batch(
4854
4866
  ...entityOps,
4867
+ ...prepareKindBackfills(kindBackfills),
4855
4868
  ...toCreate.map(
4856
4869
  (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
4857
4870
  record._setRaw("memory_id", memoryId);
@@ -5940,27 +5953,36 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
5940
5953
  if (!entityCtx) {
5941
5954
  throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
5942
5955
  }
5956
+ const uniqueIds = Array.from(new Set(memoryIds));
5957
+ if (uniqueIds.length === 0) return [];
5943
5958
  const filled = [];
5944
- for (const id of Array.from(new Set(memoryIds))) {
5945
- let record;
5946
- try {
5947
- record = await ctx.vaultMemoryCollection.find(id);
5948
- } catch {
5949
- continue;
5950
- }
5951
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
5952
- if (parseTopics(record.topics) !== null) continue;
5953
- const links = await entityCtx.memoryEntityCollection.query(import_watermelondb9.Q.where("memory_id", id)).unsafeFetchRaw();
5954
- const entityIds = links.map((l) => String(l.entity_id));
5955
- if (entityIds.length === 0) continue;
5956
- const entities = await entityCtx.entityCollection.query(import_watermelondb9.Q.where("id", import_watermelondb9.Q.oneOf(entityIds))).fetch();
5957
- if (entities.length === 0) continue;
5958
- const source = record.topicsUserManaged ? "user" : "auto";
5959
+ const CHUNK = 500;
5960
+ for (let i = 0; i < uniqueIds.length; i += CHUNK) {
5961
+ const chunkIds = uniqueIds.slice(i, i + CHUNK);
5959
5962
  await ctx.database.write(async () => {
5960
- const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, id, entities, [], source);
5961
- if (!topicsOp) return;
5962
- await ctx.database.batch(topicsOp);
5963
- filled.push(id);
5963
+ const writes = [];
5964
+ for (const id of chunkIds) {
5965
+ let record;
5966
+ try {
5967
+ record = await ctx.vaultMemoryCollection.find(id);
5968
+ } catch {
5969
+ continue;
5970
+ }
5971
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
5972
+ if (parseTopics(record.topics) !== null) continue;
5973
+ const links = await entityCtx.memoryEntityCollection.query(import_watermelondb9.Q.where("memory_id", id)).unsafeFetchRaw();
5974
+ const entityIds = links.map((l) => String(l.entity_id));
5975
+ if (entityIds.length === 0) continue;
5976
+ const entities = await entityCtx.entityCollection.query(import_watermelondb9.Q.where("id", import_watermelondb9.Q.oneOf(entityIds))).fetch();
5977
+ if (entities.length === 0) continue;
5978
+ const source = record.topicsUserManaged ? "user" : "auto";
5979
+ const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
5980
+ if (write) writes.push(write);
5981
+ }
5982
+ if (writes.length === 0) return;
5983
+ const prepared = writes.map(prepareMemoryTopicsUpdate);
5984
+ await ctx.database.batch(...prepared);
5985
+ for (const write of writes) filled.push(write.row.id);
5964
5986
  });
5965
5987
  }
5966
5988
  return filled;
@@ -9573,6 +9595,7 @@ __export(index_exports, {
9573
9595
  hasEncryptionKey: () => hasEncryptionKey,
9574
9596
  ingestPublishedPhotoMemoriesOp: () => ingestPublishedPhotoMemoriesOp,
9575
9597
  injectionSignatureCatalog: () => injectionSignatureCatalog,
9598
+ isDegradedTopicSkip: () => isDegradedTopicSkip,
9576
9599
  isPiiRedactor: () => isPiiRedactor,
9577
9600
  isRerankerAvailable: () => isRerankerAvailable,
9578
9601
  moveMemoriesToFolderOp: () => moveMemoriesToFolderOp,
@@ -17095,7 +17118,7 @@ function createAutoExtractor(options) {
17095
17118
  const t0 = Date.now();
17096
17119
  void (async () => {
17097
17120
  try {
17098
- const { candidates, results, failedCount, outcome } = await extractAndRetain(
17121
+ const { candidates, results, failedCount, outcome, failure } = await extractAndRetain(
17099
17122
  window2,
17100
17123
  retainCtx,
17101
17124
  {
@@ -17135,7 +17158,11 @@ function createAutoExtractor(options) {
17135
17158
  failedCount,
17136
17159
  durationMs: Date.now() - t0,
17137
17160
  conversationId,
17138
- outcome
17161
+ outcome,
17162
+ // Only set alongside `outcome: "empty-after-retry"`. Spread so the key
17163
+ // is absent rather than explicitly undefined on a healthy turn —
17164
+ // analytics backends store an explicit undefined as a real value.
17165
+ ...failure !== void 0 && { failure }
17139
17166
  });
17140
17167
  } catch (err) {
17141
17168
  options.onError?.(err instanceof Error ? err : new Error(String(err)), conversationId);
@@ -18437,6 +18464,18 @@ function parseTopicResponse(parsed, validIds) {
18437
18464
  }
18438
18465
  return out;
18439
18466
  }
18467
+ var DEGRADED_TOPIC_SKIP = {
18468
+ excluded: false,
18469
+ "link-declined": false,
18470
+ "stamp-declined": false,
18471
+ "llm-unanswered": true,
18472
+ unreadable: true,
18473
+ "not-found": true,
18474
+ "link-failed": true
18475
+ };
18476
+ function isDegradedTopicSkip(reason) {
18477
+ return DEGRADED_TOPIC_SKIP[reason] === true;
18478
+ }
18440
18479
  async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
18441
18480
  const entityCtx = ctx.entityCtx;
18442
18481
  if (!entityCtx) {
@@ -18445,17 +18484,24 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
18445
18484
  const log = getLogger();
18446
18485
  const extractedAt = options.now ?? Date.now();
18447
18486
  const skippedIds = [];
18487
+ const skippedReasons = /* @__PURE__ */ new Map();
18488
+ const skip = (id, reason) => {
18489
+ if (skippedReasons.has(id)) return;
18490
+ skippedIds.push(id);
18491
+ skippedReasons.set(id, reason);
18492
+ };
18448
18493
  const inputs = [];
18449
- for (const id of memoryIds) {
18494
+ for (const id of new Set(memoryIds)) {
18450
18495
  let record;
18451
18496
  try {
18452
18497
  record = await ctx.vaultMemoryCollection.find(id);
18453
- } catch {
18454
- skippedIds.push(id);
18498
+ } catch (err) {
18499
+ log.warn("[memory/topics] vault lookup failed for extraction", err);
18500
+ skip(id, "not-found");
18455
18501
  continue;
18456
18502
  }
18457
18503
  if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
18458
- skippedIds.push(id);
18504
+ skip(id, "excluded");
18459
18505
  continue;
18460
18506
  }
18461
18507
  try {
@@ -18468,7 +18514,7 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
18468
18514
  inputs.push({ id, content: stored.content });
18469
18515
  } catch (err) {
18470
18516
  log.warn("[memory/topics] failed to load memory for extraction", err);
18471
- skippedIds.push(id);
18517
+ skip(id, "unreadable");
18472
18518
  }
18473
18519
  }
18474
18520
  const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
@@ -18476,19 +18522,19 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
18476
18522
  for (const input of inputs) {
18477
18523
  const entities = entitiesByMemory.get(input.id);
18478
18524
  if (entities === void 0) {
18479
- skippedIds.push(input.id);
18525
+ skip(input.id, "llm-unanswered");
18480
18526
  continue;
18481
18527
  }
18482
18528
  try {
18483
18529
  const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
18484
18530
  if (linked === null) {
18485
- skippedIds.push(input.id);
18531
+ skip(input.id, "link-declined");
18486
18532
  entitiesByMemory.delete(input.id);
18487
18533
  continue;
18488
18534
  }
18489
18535
  } catch (err) {
18490
18536
  log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
18491
- skippedIds.push(input.id);
18537
+ skip(input.id, "link-failed");
18492
18538
  entitiesByMemory.delete(input.id);
18493
18539
  continue;
18494
18540
  }
@@ -18498,11 +18544,11 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
18498
18544
  const stampedSet = new Set(stampedIds);
18499
18545
  for (const id of toStamp) {
18500
18546
  if (!stampedSet.has(id)) {
18501
- skippedIds.push(id);
18547
+ skip(id, "stamp-declined");
18502
18548
  entitiesByMemory.delete(id);
18503
18549
  }
18504
18550
  }
18505
- return { entitiesByMemory, stampedIds, skippedIds };
18551
+ return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
18506
18552
  }
18507
18553
 
18508
18554
  // src/lib/memory/verifySupport.ts
@@ -24534,6 +24580,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
24534
24580
  hasEncryptionKey,
24535
24581
  ingestPublishedPhotoMemoriesOp,
24536
24582
  injectionSignatureCatalog,
24583
+ isDegradedTopicSkip,
24537
24584
  isPiiRedactor,
24538
24585
  isRerankerAvailable,
24539
24586
  moveMemoriesToFolderOp,
@@ -6768,6 +6768,14 @@ declare function relinkMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryI
6768
6768
  * row has: a curated memory's topics are recorded as `user`, everything else as
6769
6769
  * `auto`. Skips deleted, foreign-user, unlinked rows, and rows that already have
6770
6770
  * a record. Returns the ids filled.
6771
+ *
6772
+ * Runs as ONE writer over the whole (caller-bounded) list, in two phases:
6773
+ * resolve every row's write — all the awaits — and only then prepare and batch,
6774
+ * synchronously. Resolving and preparing per row inside its own writer is what
6775
+ * fired WatermelonDB's "wasn't sent to batch() synchronously" diagnostic once
6776
+ * per memory (~107 on a single dev launch, sdk#891); it also cost N writes.
6777
+ * Same treatment as {@link stampTopicsExtractedAtOp}, including its
6778
+ * transpilation hazard — the prepare pass MUST stay a `.map()`.
6771
6779
  */
6772
6780
  declare function backfillMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryIds: readonly string[]): Promise<string[]>;
6773
6781
  declare function deleteAllVaultMemoriesForUserOp(ctx: VaultMemoryOperationsContext, userId: string): Promise<number>;
@@ -7230,6 +7238,22 @@ interface TurnCompleteEvent {
7230
7238
  * previously indistinguishable (both surfaced as zero candidates).
7231
7239
  */
7232
7240
  outcome: ExtractOutcome;
7241
+ /**
7242
+ * Present only alongside `outcome: "empty-after-retry"` — WHICH failure ended
7243
+ * the turn (#888).
7244
+ *
7245
+ * `outcome` says extraction gave up; this says why, from a stable enum. The
7246
+ * distinction is the whole point: a 2026-08-11 audit measured ~63% of
7247
+ * production extraction turns ending in `empty-after-retry` and could not tell
7248
+ * from telemetry whether the cause was the freeloader 403 everyone assumed or
7249
+ * something else. It took a Prometheus cross-check to find the real one — the
7250
+ * portal returning HTTP 200 with an empty body, which it counts as a success.
7251
+ *
7252
+ * Forward `failure.reason` into your extraction analytics event; all three
7253
+ * fields are bounded (an enum, an HTTP status, a small attempt count) and none
7254
+ * carries content.
7255
+ */
7256
+ failure?: PortalLlmFailure;
7233
7257
  }
7234
7258
  /** @public */
7235
7259
  /**
@@ -8495,6 +8519,39 @@ interface TopicExtractOptions extends PortalLlmAuth {
8495
8519
  * later sweep, never stamp them.
8496
8520
  */
8497
8521
  declare function extractEntitiesForMemories(memories: readonly TopicExtractionInput[], options: TopicExtractOptions): Promise<Map<string, ExtractedEntity[]>>;
8522
+ /**
8523
+ * Why one memory was skipped by a topic sweep.
8524
+ *
8525
+ * Split along the line that actually matters operationally — did the sweep
8526
+ * DECLINE this row on purpose, or did something BREAK:
8527
+ *
8528
+ * Deliberate (healthy; a sweep of nothing but these is a success):
8529
+ * - `excluded` — deleted, owned by another user, or `topicsUserManaged`.
8530
+ * - `link-declined` — the entity-link write's in-row guard declined (the row
8531
+ * became user-managed / deleted / absent mid-run).
8532
+ * - `stamp-declined` — same, caught by the stamp op's own re-check.
8533
+ *
8534
+ * Degraded (something is wrong; see {@link isDegradedTopicSkip}):
8535
+ * - `llm-unanswered` — the batch failed or the model omitted this id. THE one
8536
+ * to alarm on: it is how a wholly broken sweep looks.
8537
+ * - `unreadable` — the row could not be loaded/decrypted.
8538
+ * - `not-found` — the lookup threw (absent row or read fault).
8539
+ * - `link-failed` — the entity-link write threw.
8540
+ *
8541
+ * @public
8542
+ */
8543
+ type TopicSkipReason = "excluded" | "link-declined" | "stamp-declined" | "llm-unanswered" | "unreadable" | "not-found" | "link-failed";
8544
+ /**
8545
+ * Whether a skip reason means the sweep FAILED on that row, rather than
8546
+ * deliberately passing over it.
8547
+ *
8548
+ * Exported so callers classify identically instead of each re-deriving the
8549
+ * split — the reason this type exists is that one wrong grouping turns a broken
8550
+ * sweep back into a healthy-looking one.
8551
+ *
8552
+ * @public
8553
+ */
8554
+ declare function isDegradedTopicSkip(reason: TopicSkipReason): boolean;
8498
8555
  /** Outcome of one {@link extractAndLinkEntitiesForMemoriesOp} run. */
8499
8556
  interface TopicExtractionRunResult {
8500
8557
  /** memoryId → entities the LLM returned (post-validation, post-linking). */
@@ -8507,6 +8564,24 @@ interface TopicExtractionRunResult {
8507
8564
  * LLM batches. Skipped ids are not stamped, so failed batches are retried
8508
8565
  * by a later sweep — callers should apply their own attempt caps. */
8509
8566
  skippedIds: string[];
8567
+ /**
8568
+ * Why each id in {@link skippedIds} was skipped.
8569
+ *
8570
+ * `skippedIds` alone cannot distinguish a sweep that deliberately declined
8571
+ * work from one that FAILED: a run where every LLM batch errored and a run
8572
+ * over rows the user has taken manual control of produce an identical array.
8573
+ * That is the same blindness `outcome: 'empty-after-retry'` had before #888 —
8574
+ * a degradation wearing the shape of normal control flow.
8575
+ *
8576
+ * It matters here because topics feed the entity recall lane, so a silently
8577
+ * failing sweep means memories that exist but cannot be found by entity, with
8578
+ * nothing in production saying so.
8579
+ *
8580
+ * Populated in lockstep with `skippedIds` (single `skip()` helper), so the two
8581
+ * cannot drift. Group by {@link isDegradedTopicSkip} to separate "declined" from
8582
+ * "broke".
8583
+ */
8584
+ skippedReasons: Map<string, TopicSkipReason>;
8510
8585
  }
8511
8586
  /**
8512
8587
  * Run LLM topic extraction over existing vault memories and persist the
@@ -10353,4 +10428,4 @@ declare function refreshNotionAccessToken(params: NotionRefreshTokenParams): Pro
10353
10428
  */
10354
10429
  declare function createNotionTools(getAccessToken: () => string | null, requestNotionAccess: () => Promise<string>): ToolConfig[];
10355
10430
 
10356
- export { type AutoExtractMessage, type AutoExtractor, type Budget, CHUNKS_DISCARDED_ORIGIN, type CachedChunkVectors, type CachedServerTools, Conversation as ChatConversation, Message as ChatMessage, type ChatRole, type ChunkVectorCache, type ChunkingOptions, type ConsolidationFallbackReason, type ConversationMemoryInput, ConversationMemory as ConversationMemoryModel, type ConversationMemoryOperationsContext, type CreateAutoExtractorOptions, type CreateConversationOptions, type CreateDecaySweeperOptions, type CreateMessageOptions, type CreateVaultFolderOptions, type CreateVaultMemoryOptions, type CryptoPriceClassification, type CryptoPricePreProcessorOptions, DEFAULT_CACHE_EXPIRATION_MS, DEFAULT_CHUNK_CACHE_SIZE, DEFAULT_CHUNK_OVERLAP, DEFAULT_CHUNK_SIZE, DEFAULT_DECAY_POLICY, DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP, DEFAULT_MIN_CHUNK_SIZE, DEFAULT_PROFILE_FACETS, DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, DEFAULT_PROFILE_PROOF_ALPHA, DEFAULT_PROFILE_TREND_MULTIPLIERS, DEFAULT_VAULT_CACHE_SIZE, DatabaseManager, type DatabaseManagerLogger, type DatabaseManagerOptions, type DecayCandidateRaw, type DecayClassifier, type DecayInput, type DecayPolicy, type DecaySweepResult, type DecaySweeper, type DecayVerdict, ENTITY_FANOUT, type EmbeddedWalletSignerFn, EncryptionKeyMissingError, type ExtractFactsOptions, type ExtractOutcome, type ExtractedCandidate, type ExtractedEntity, type ExtractionCursorStore, type FactType, type FileMetadata, type FlushResult, type GetConversationsPageOptions, type GetMessagesPageOptions, type GraphTraversalOptions, HARD_DELETE_WINDOW_MS, INFERENCE_ID_HEADER, type InjectionClassifierOptions, type InjectionReason, type LazyStoredConversation, type LlmDecayClassifierOptions, type LlmNeighborRefinerOptions, type Logger, LoggerProvider, type LoggerProviderProps, MAX_HOPS, MEDIUM_TTL_MS, type MemoriesNeedingTopicExtraction, type EmbeddingOptions as MemoryEngineEmbeddingOptions, type MemoryEngineResult, type MemoryEngineSearchOptions, type MemoryExtractedEvent, type MemoryKind, type MemoryQuarantinedEvent, type MemoryToVerify, type MemoryVaultSearchOptions, type MemoryVaultToolOptions, type MemoryVerification, type MessageRedactionResult, type MessageSkeleton, NEVER_TTL_MS, NODE_BUDGET, NOTION_OAUTH_CONFIG, type NeighborRefiner, type NotionAuthUrlParams, type NotionClientRegistration, type NotionExchangeCodeParams, type NotionOAuthEndpoints, type NotionPKCEChallenge, type NotionRefreshTokenParams, type NotionTokenResponse, type NowSource, type ObservationTrend, type ObservationTrendInput, PAST_EVENT_GRACE_MS, PII_PATTERNS, PROFILE_DOC_VERSION, type PhotoIngestResult, type PhotoMediaRef, type PiiCategory, type PiiMatch, type PiiPattern, PiiRedactor, type PiiRedactorOptions, type PlatformStorage, type PortalLlmAuth, type PortalLlmFailure, type PortalLlmFailureReason, type ProfileConfigFingerprint, type ProfileDoc, type ProfileFacet, type ProfileFacetKey, type ProfileSalienceInput, type ProfileSection, type PromptPreProcessor, type PromptPreProcessorContext, type PublishedPhotoMemory, type QuantizedEmbedding, type QuarantinedMemoryInfo, QueueManager, type QueueStatus, RECALL_MAX_LIMIT, RECALL_TOOL_NAME, type RankableVaultMemory, type RankedMemory, type RankedProfileCandidate, type RecallContext, type RecallDegradation, type RecallDiagnostics, type RecallOptions, type RecallResult, type RecallToolCallbacks, type RecallToolOptions, type RecencyOptions, type RedactionResult, type ReflectOptions, type ReflectResult, type RequestEncryptionKeyOptions, RerankerUnavailableError, type ResumeStreamOptions, type ResumeStreamResult, type ResumeStreamWithStorageResult, type RetainAction, type RetainContext, type RetainOptions, type RetainResult, type RetainSource, SDK_SCHEMA_VERSION, SHORT_TTL_MS, STREAM_RESUMABLE_HEADER, type ScoreBreakdown, type ScoreProfileSalienceOptions, type ScreenResult, type ScreenedCandidate, type SearchSource, type SendMessageWithStorageArgs, type SendMessageWithStorageDetachedResult, type SendMessageWithStorageResult, type ServerToolsOptions, type ServerToolsResponse, type SignMessageFn, type StockPriceClassification, type StockPricePreProcessorOptions, type ChatCompletionUsage as StoredChatCompletionUsage, type StoredConversation, type StoredConversationMemory, type StoredMessage, type StoredMessageWithSimilarity, type StoredVaultFolder, VaultFolder as StoredVaultFolderModel, type StoredVaultMemory, VaultMemory as StoredVaultMemoryModel, StreamExpiredError, type StreamMetaEvent, type StreamResumeHandle, type SynthesizeProfileOptions, TOOL_RESULT_ORIGIN, TOPICS_EXTRACTION_VERSION, TOPIC_EXTRACTION_BATCH_SIZE, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS, type TextChunk, type TopicExtractOptions, type TopicExtractionInput, type TopicExtractionRunResult, type TurnCompleteEvent, type TurnSkippedEvent, type UncheckedReason, type UnverifiableReason, type UpdateVaultFolderOptions, type UpdateVaultMemoryOptions, type UseChatStorageOptions, type UseChatStorageResult, type UseCreditsOptions, type UseCreditsResult, type UseModelsOptions, type UseModelsResult, VAULT_SIZE_HOP_CAP, type VaultEmbeddingCache, type VaultFolderOperationsContext, type VaultMemoryOperationsContext, type VaultMemoryVisibility, type VaultSaveOperation, type VaultSearchResult, type VerificationSources, type VerifyMemoriesForPublishOptions, WalletPoller, type WeatherClassification, type WeatherPreProcessorOptions, type WebSearchClassification, type WebSearchPreProcessorOptions, addConversationMemoriesOp, archiveVaultMemoryOp, backfillMemoryTopicsOp, buildNotionAuthUrl, capHopsForDensity, chatStorageMigrations, chatStorageSchema, chunkAndEmbedAllMessages, chunkAndEmbedMessage, chunkText, classifyCryptoPrice, classifyCryptoPriceBatch, classifyDecay, classifyInjectionCandidates, classifyObservationTrend, classifyStockPrice, classifyStockPriceBatch, classifyWeather, classifyWeatherBatch, classifyWebSearch, classifyWebSearchBatch, clearAllEncryptionKeys, clearAllEncryptionState, clearConversationMemoriesOp, clearEncryptionKey, clearLazyTitleCache, clearServerToolsCache, consoleLogger, conversationMemoryToStored, cosineInt8, createAutoExtractor, createChunkVectorCache, createCryptoPricePreProcessor, createDecaySweeper, createLlmDecayClassifier, createLlmNeighborRefiner, createMemoryEngineTool, createMemoryVaultSearchTool, createMemoryVaultTool, createMessageSourceResolver, createNotionTools, createPlatformCursorStore, createRecallTool, createStockPricePreProcessor, createStreamingDeAnonymizer, createVaultEmbeddingCache, createVaultFolderOp, createVaultMemoriesBatchOp, createVaultMemoryOp, createWeatherPreProcessor, createWebSearchPreProcessor, decodeChunkVector, decryptConversationTitle, deleteAllVaultMemoriesForUserOp, deleteVaultFolderOp, deleteVaultMemoryOp, dequantizeEmbedding, discoverNotionOAuthEndpoints, eagerEmbedContent, embedAllMessages, embedMessage, encodeChunkVector, ensureDefaultFoldersOp, exchangeNotionCode, extractAndLinkEntitiesForMemoriesOp, extractAndRetain, extractEntitiesForMemories, extractFacts, generateConversationId, generateEmbedding, generateEmbeddings, generateNotionPKCE, getAllVaultFoldersOp, getAllVaultMemoriesOp, getAllVaultMemoryContentsOp, getCachedServerTools, getConversationMemoriesOp, getConversationsByProjectLazyOp, getConversationsLazyOp, getConversationsPageOp, getDecayCandidatesRawOp, getLogger, getMemoriesNeedingTopicExtractionOp, getServerTools, getUnfiledVaultMemoriesOp, getVaultFolderMemoryCountOp, getVaultMemoriesByIdsOp, getVaultMemoryOp, getVaultRankingProjectionsOp, hardDeleteDecayedOp, hasEncryptionKey, ingestPublishedPhotoMemoriesOp, injectionSignatureCatalog, isPiiRedactor, isRerankerAvailable, moveMemoriesToFolderOp, noopLogger, onKeyAvailable, parseMedia, preEmbedVaultMemories, quantizeEmbedding, queueManager, rankProfileCandidates, recall, reflect, refreshEncryptionKeyIfMatches, refreshNotionAccessToken, registerNotionClient, relinkMemoryTopicsOp, requestEncryptionKey, resolvePiiRedactor, restoreVaultMemoryOp, resumeStream, retain, scoreProfileSalience, screenCandidatesForInjection, sdkMigrations, sdkModelClasses, sdkSchema, searchVaultMemories, seedEncryptionKeys, setLogger, setMemoryVisibilityOp, shouldChunkMessage, stampTopicsExtractedAtOp, streamCancelPath, streamReplayPath, summarizeObservationTrends, supersedeVaultMemoryOp, synthesizeProfile, traverseGraphLane, ttlForType, updateVaultFolderContextOp, updateVaultFolderOp, updateVaultMemoryEmbeddingOp, updateVaultMemoryOp, upsertMessageOp, useChat, useChatStorage, useCredits, useEncryption, useModels, verifyMemoriesForPublish, xhrTransport };
10431
+ export { type AutoExtractMessage, type AutoExtractor, type Budget, CHUNKS_DISCARDED_ORIGIN, type CachedChunkVectors, type CachedServerTools, Conversation as ChatConversation, Message as ChatMessage, type ChatRole, type ChunkVectorCache, type ChunkingOptions, type ConsolidationFallbackReason, type ConversationMemoryInput, ConversationMemory as ConversationMemoryModel, type ConversationMemoryOperationsContext, type CreateAutoExtractorOptions, type CreateConversationOptions, type CreateDecaySweeperOptions, type CreateMessageOptions, type CreateVaultFolderOptions, type CreateVaultMemoryOptions, type CryptoPriceClassification, type CryptoPricePreProcessorOptions, DEFAULT_CACHE_EXPIRATION_MS, DEFAULT_CHUNK_CACHE_SIZE, DEFAULT_CHUNK_OVERLAP, DEFAULT_CHUNK_SIZE, DEFAULT_DECAY_POLICY, DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP, DEFAULT_MIN_CHUNK_SIZE, DEFAULT_PROFILE_FACETS, DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, DEFAULT_PROFILE_PROOF_ALPHA, DEFAULT_PROFILE_TREND_MULTIPLIERS, DEFAULT_VAULT_CACHE_SIZE, DatabaseManager, type DatabaseManagerLogger, type DatabaseManagerOptions, type DecayCandidateRaw, type DecayClassifier, type DecayInput, type DecayPolicy, type DecaySweepResult, type DecaySweeper, type DecayVerdict, ENTITY_FANOUT, type EmbeddedWalletSignerFn, EncryptionKeyMissingError, type ExtractFactsOptions, type ExtractOutcome, type ExtractedCandidate, type ExtractedEntity, type ExtractionCursorStore, type FactType, type FileMetadata, type FlushResult, type GetConversationsPageOptions, type GetMessagesPageOptions, type GraphTraversalOptions, HARD_DELETE_WINDOW_MS, INFERENCE_ID_HEADER, type InjectionClassifierOptions, type InjectionReason, type LazyStoredConversation, type LlmDecayClassifierOptions, type LlmNeighborRefinerOptions, type Logger, LoggerProvider, type LoggerProviderProps, MAX_HOPS, MEDIUM_TTL_MS, type MemoriesNeedingTopicExtraction, type EmbeddingOptions as MemoryEngineEmbeddingOptions, type MemoryEngineResult, type MemoryEngineSearchOptions, type MemoryExtractedEvent, type MemoryKind, type MemoryQuarantinedEvent, type MemoryToVerify, type MemoryVaultSearchOptions, type MemoryVaultToolOptions, type MemoryVerification, type MessageRedactionResult, type MessageSkeleton, NEVER_TTL_MS, NODE_BUDGET, NOTION_OAUTH_CONFIG, type NeighborRefiner, type NotionAuthUrlParams, type NotionClientRegistration, type NotionExchangeCodeParams, type NotionOAuthEndpoints, type NotionPKCEChallenge, type NotionRefreshTokenParams, type NotionTokenResponse, type NowSource, type ObservationTrend, type ObservationTrendInput, PAST_EVENT_GRACE_MS, PII_PATTERNS, PROFILE_DOC_VERSION, type PhotoIngestResult, type PhotoMediaRef, type PiiCategory, type PiiMatch, type PiiPattern, PiiRedactor, type PiiRedactorOptions, type PlatformStorage, type PortalLlmAuth, type PortalLlmFailure, type PortalLlmFailureReason, type ProfileConfigFingerprint, type ProfileDoc, type ProfileFacet, type ProfileFacetKey, type ProfileSalienceInput, type ProfileSection, type PromptPreProcessor, type PromptPreProcessorContext, type PublishedPhotoMemory, type QuantizedEmbedding, type QuarantinedMemoryInfo, QueueManager, type QueueStatus, RECALL_MAX_LIMIT, RECALL_TOOL_NAME, type RankableVaultMemory, type RankedMemory, type RankedProfileCandidate, type RecallContext, type RecallDegradation, type RecallDiagnostics, type RecallOptions, type RecallResult, type RecallToolCallbacks, type RecallToolOptions, type RecencyOptions, type RedactionResult, type ReflectOptions, type ReflectResult, type RequestEncryptionKeyOptions, RerankerUnavailableError, type ResumeStreamOptions, type ResumeStreamResult, type ResumeStreamWithStorageResult, type RetainAction, type RetainContext, type RetainOptions, type RetainResult, type RetainSource, SDK_SCHEMA_VERSION, SHORT_TTL_MS, STREAM_RESUMABLE_HEADER, type ScoreBreakdown, type ScoreProfileSalienceOptions, type ScreenResult, type ScreenedCandidate, type SearchSource, type SendMessageWithStorageArgs, type SendMessageWithStorageDetachedResult, type SendMessageWithStorageResult, type ServerToolsOptions, type ServerToolsResponse, type SignMessageFn, type StockPriceClassification, type StockPricePreProcessorOptions, type ChatCompletionUsage as StoredChatCompletionUsage, type StoredConversation, type StoredConversationMemory, type StoredMessage, type StoredMessageWithSimilarity, type StoredVaultFolder, VaultFolder as StoredVaultFolderModel, type StoredVaultMemory, VaultMemory as StoredVaultMemoryModel, StreamExpiredError, type StreamMetaEvent, type StreamResumeHandle, type SynthesizeProfileOptions, TOOL_RESULT_ORIGIN, TOPICS_EXTRACTION_VERSION, TOPIC_EXTRACTION_BATCH_SIZE, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS, type TextChunk, type TopicExtractOptions, type TopicExtractionInput, type TopicExtractionRunResult, type TopicSkipReason, type TurnCompleteEvent, type TurnSkippedEvent, type UncheckedReason, type UnverifiableReason, type UpdateVaultFolderOptions, type UpdateVaultMemoryOptions, type UseChatStorageOptions, type UseChatStorageResult, type UseCreditsOptions, type UseCreditsResult, type UseModelsOptions, type UseModelsResult, VAULT_SIZE_HOP_CAP, type VaultEmbeddingCache, type VaultFolderOperationsContext, type VaultMemoryOperationsContext, type VaultMemoryVisibility, type VaultSaveOperation, type VaultSearchResult, type VerificationSources, type VerifyMemoriesForPublishOptions, WalletPoller, type WeatherClassification, type WeatherPreProcessorOptions, type WebSearchClassification, type WebSearchPreProcessorOptions, addConversationMemoriesOp, archiveVaultMemoryOp, backfillMemoryTopicsOp, buildNotionAuthUrl, capHopsForDensity, chatStorageMigrations, chatStorageSchema, chunkAndEmbedAllMessages, chunkAndEmbedMessage, chunkText, classifyCryptoPrice, classifyCryptoPriceBatch, classifyDecay, classifyInjectionCandidates, classifyObservationTrend, classifyStockPrice, classifyStockPriceBatch, classifyWeather, classifyWeatherBatch, classifyWebSearch, classifyWebSearchBatch, clearAllEncryptionKeys, clearAllEncryptionState, clearConversationMemoriesOp, clearEncryptionKey, clearLazyTitleCache, clearServerToolsCache, consoleLogger, conversationMemoryToStored, cosineInt8, createAutoExtractor, createChunkVectorCache, createCryptoPricePreProcessor, createDecaySweeper, createLlmDecayClassifier, createLlmNeighborRefiner, createMemoryEngineTool, createMemoryVaultSearchTool, createMemoryVaultTool, createMessageSourceResolver, createNotionTools, createPlatformCursorStore, createRecallTool, createStockPricePreProcessor, createStreamingDeAnonymizer, createVaultEmbeddingCache, createVaultFolderOp, createVaultMemoriesBatchOp, createVaultMemoryOp, createWeatherPreProcessor, createWebSearchPreProcessor, decodeChunkVector, decryptConversationTitle, deleteAllVaultMemoriesForUserOp, deleteVaultFolderOp, deleteVaultMemoryOp, dequantizeEmbedding, discoverNotionOAuthEndpoints, eagerEmbedContent, embedAllMessages, embedMessage, encodeChunkVector, ensureDefaultFoldersOp, exchangeNotionCode, extractAndLinkEntitiesForMemoriesOp, extractAndRetain, extractEntitiesForMemories, extractFacts, generateConversationId, generateEmbedding, generateEmbeddings, generateNotionPKCE, getAllVaultFoldersOp, getAllVaultMemoriesOp, getAllVaultMemoryContentsOp, getCachedServerTools, getConversationMemoriesOp, getConversationsByProjectLazyOp, getConversationsLazyOp, getConversationsPageOp, getDecayCandidatesRawOp, getLogger, getMemoriesNeedingTopicExtractionOp, getServerTools, getUnfiledVaultMemoriesOp, getVaultFolderMemoryCountOp, getVaultMemoriesByIdsOp, getVaultMemoryOp, getVaultRankingProjectionsOp, hardDeleteDecayedOp, hasEncryptionKey, ingestPublishedPhotoMemoriesOp, injectionSignatureCatalog, isDegradedTopicSkip, isPiiRedactor, isRerankerAvailable, moveMemoriesToFolderOp, noopLogger, onKeyAvailable, parseMedia, preEmbedVaultMemories, quantizeEmbedding, queueManager, rankProfileCandidates, recall, reflect, refreshEncryptionKeyIfMatches, refreshNotionAccessToken, registerNotionClient, relinkMemoryTopicsOp, requestEncryptionKey, resolvePiiRedactor, restoreVaultMemoryOp, resumeStream, retain, scoreProfileSalience, screenCandidatesForInjection, sdkMigrations, sdkModelClasses, sdkSchema, searchVaultMemories, seedEncryptionKeys, setLogger, setMemoryVisibilityOp, shouldChunkMessage, stampTopicsExtractedAtOp, streamCancelPath, streamReplayPath, summarizeObservationTrends, supersedeVaultMemoryOp, synthesizeProfile, traverseGraphLane, ttlForType, updateVaultFolderContextOp, updateVaultFolderOp, updateVaultMemoryEmbeddingOp, updateVaultMemoryOp, upsertMessageOp, useChat, useChatStorage, useCredits, useEncryption, useModels, verifyMemoriesForPublish, xhrTransport };