@anuma/sdk 6.1.1 → 6.3.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.
@@ -1284,7 +1284,8 @@ function messageToStoredRaw(message, projection) {
1284
1284
  thinking: message.thinking,
1285
1285
  parentMessageId: message.parentMessageId,
1286
1286
  feedback: message.feedback || null,
1287
- toolCallEvents: parseJsonField(toolCallEventsRaw)
1287
+ toolCallEvents: parseJsonField(toolCallEventsRaw),
1288
+ origin: message.origin
1288
1289
  };
1289
1290
  }
1290
1291
  async function messageToStored(message, walletAddress, signMessage, embeddedWalletSigner, projection) {
@@ -1345,7 +1346,11 @@ function messageRawToStoredRaw(raw, projection) {
1345
1346
  thinking: raw.thinking,
1346
1347
  parentMessageId: raw.parent_message_id,
1347
1348
  feedback: raw.feedback || null,
1348
- toolCallEvents: parseJsonField(raw.tool_call_events)
1349
+ toolCallEvents: parseJsonField(raw.tool_call_events),
1350
+ // Load-bearing on this path specifically: getMessagesOp reads raws, and it is
1351
+ // what the deferred embedding sweep iterates, so the provenance gate depends
1352
+ // on `origin` surviving the raw mapper as well as the Model one.
1353
+ origin: raw.origin
1349
1354
  };
1350
1355
  }
1351
1356
  async function messageRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner, projection) {
@@ -1667,6 +1672,7 @@ function applyMessageFields(msg, encryptedOpts) {
1667
1672
  const tceValue = typeof encryptedOpts.toolCallEvents === "string" ? encryptedOpts.toolCallEvents : JSON.stringify(encryptedOpts.toolCallEvents);
1668
1673
  msg._setRaw("tool_call_events", tceValue);
1669
1674
  }
1675
+ if (encryptedOpts.origin) msg._setRaw("origin", encryptedOpts.origin);
1670
1676
  }
1671
1677
  async function createMessageOp(ctx, opts) {
1672
1678
  if (opts.uniqueId) {
@@ -2009,7 +2015,8 @@ function makeSyntheticStoredMessage(opts) {
2009
2015
  thoughtProcess: opts.thoughtProcess,
2010
2016
  thinking: opts.thinking,
2011
2017
  parentMessageId: opts.parentMessageId,
2012
- toolCallEvents: opts.toolCallEvents
2018
+ toolCallEvents: opts.toolCallEvents,
2019
+ origin: opts.origin
2013
2020
  };
2014
2021
  }
2015
2022
  function makeSyntheticStoredConversation(opts, defaultTitle) {
@@ -2403,6 +2410,22 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
2403
2410
  };
2404
2411
  }
2405
2412
 
2413
+ // src/lib/db/memoryVault/types.ts
2414
+ function parseMedia(value) {
2415
+ if (typeof value !== "string" || value === "") return null;
2416
+ try {
2417
+ const parsed = JSON.parse(value);
2418
+ if (!Array.isArray(parsed)) return null;
2419
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
2420
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
2421
+ objectKey: r.objectKey ?? r.object_key ?? null
2422
+ })).filter((r) => Number.isFinite(r.feedItemId));
2423
+ return refs.length > 0 ? refs : null;
2424
+ } catch {
2425
+ return null;
2426
+ }
2427
+ }
2428
+
2406
2429
  // src/lib/db/memoryVault/operations.ts
2407
2430
  function visibilityOrPrivate(value) {
2408
2431
  return value === "public" ? value : "private";
@@ -2466,6 +2489,7 @@ function vaultMemoryToStoredRaw(memory) {
2466
2489
  sourceChunkIds,
2467
2490
  proofCount: memory.proofCount ?? null,
2468
2491
  source: memory.source ?? null,
2492
+ media: parseMedia(memory.media),
2469
2493
  eventTimeStart: memory.eventTimeStart ?? null,
2470
2494
  eventTimeEnd: memory.eventTimeEnd ?? null,
2471
2495
  eventTimeKind: memory.eventTimeKind ?? null,
@@ -2748,6 +2772,7 @@ function vaultMemoryRawToStoredRaw(raw) {
2748
2772
  eventTimeKind: raw.event_time_kind ?? null,
2749
2773
  // SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
2750
2774
  topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
2775
+ media: parseMedia(raw.media),
2751
2776
  topics: parseTopics(raw.topics),
2752
2777
  topicsUpdatedAt: raw.topics_updated_at ?? null,
2753
2778
  topicsExtractedAt: raw.topics_extracted_at ?? null,
@@ -4604,6 +4629,7 @@ async function generateEmbeddings(texts, options) {
4604
4629
 
4605
4630
  // src/lib/memoryEngine/embeddings.ts
4606
4631
  var DEFAULT_MIN_CONTENT_LENGTH = 10;
4632
+ var NON_EMBEDDABLE_ORIGIN = "tool_result";
4607
4633
  async function embedMessage(ctx, messageId, options) {
4608
4634
  const message = await getMessageOp(ctx, messageId);
4609
4635
  if (!message) {
@@ -4612,6 +4638,9 @@ async function embedMessage(ctx, messageId, options) {
4612
4638
  if (message.vector && message.vector.length > 0) {
4613
4639
  return message;
4614
4640
  }
4641
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
4642
+ return message;
4643
+ }
4615
4644
  const embedding = await generateEmbedding(message.content, options);
4616
4645
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
4617
4646
  return updateMessageEmbeddingOp(ctx, messageId, embedding, embeddingModel);
@@ -4633,6 +4662,9 @@ async function embedAllMessages(ctx, options, filter) {
4633
4662
  if (message.role === "system") {
4634
4663
  continue;
4635
4664
  }
4665
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
4666
+ continue;
4667
+ }
4636
4668
  const minLength = filter?.minContentLength ?? DEFAULT_MIN_CONTENT_LENGTH;
4637
4669
  if (message.content.length < minLength) {
4638
4670
  continue;
@@ -4658,6 +4690,9 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
4658
4690
  if (message.chunks && message.chunks.length > 0) {
4659
4691
  return message;
4660
4692
  }
4693
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
4694
+ return message;
4695
+ }
4661
4696
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
4662
4697
  if (!shouldChunkMessage(message.content, chunkSize)) {
4663
4698
  const embedding = await generateEmbedding(message.content, options);
@@ -4691,6 +4726,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
4691
4726
  if (hasVector && !filter?.rechunkExisting && !isStale) continue;
4692
4727
  if (filter?.roles && !filter.roles.includes(message.role)) continue;
4693
4728
  if (message.role === "system") continue;
4729
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) continue;
4694
4730
  if (message.content.length < minLength) continue;
4695
4731
  if (shouldChunkMessage(message.content, chunkSize)) {
4696
4732
  longMessages.push({
@@ -6482,7 +6518,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
6482
6518
  subQueries = decomp.subQueries;
6483
6519
  }
6484
6520
  }
6485
- const { recall: recall2 } = await import("./recall-2IOGTAFJ.mjs");
6521
+ const { recall: recall2 } = await import("./recall-UVM2366D.mjs");
6486
6522
  let recallDegraded = [];
6487
6523
  const result = await recall2(
6488
6524
  query,
@@ -7498,6 +7534,8 @@ export {
7498
7534
  ENTITY_KINDS,
7499
7535
  linkMemoryEntitiesOp,
7500
7536
  replaceMemoryEntitiesGuardedOp,
7537
+ encryptVaultMemoryContent,
7538
+ parseMedia,
7501
7539
  vaultMemoryToStored,
7502
7540
  createVaultMemoryOp,
7503
7541
  createSupersedingMemoryOp,
@@ -1394,7 +1394,8 @@ function messageToStoredRaw(message, projection) {
1394
1394
  thinking: message.thinking,
1395
1395
  parentMessageId: message.parentMessageId,
1396
1396
  feedback: message.feedback || null,
1397
- toolCallEvents: parseJsonField(toolCallEventsRaw)
1397
+ toolCallEvents: parseJsonField(toolCallEventsRaw),
1398
+ origin: message.origin
1398
1399
  };
1399
1400
  }
1400
1401
  async function messageToStored(message, walletAddress, signMessage, embeddedWalletSigner, projection) {
@@ -1455,7 +1456,11 @@ function messageRawToStoredRaw(raw, projection) {
1455
1456
  thinking: raw.thinking,
1456
1457
  parentMessageId: raw.parent_message_id,
1457
1458
  feedback: raw.feedback || null,
1458
- toolCallEvents: parseJsonField(raw.tool_call_events)
1459
+ toolCallEvents: parseJsonField(raw.tool_call_events),
1460
+ // Load-bearing on this path specifically: getMessagesOp reads raws, and it is
1461
+ // what the deferred embedding sweep iterates, so the provenance gate depends
1462
+ // on `origin` surviving the raw mapper as well as the Model one.
1463
+ origin: raw.origin
1459
1464
  };
1460
1465
  }
1461
1466
  async function messageRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner, projection) {
@@ -1777,6 +1782,7 @@ function applyMessageFields(msg, encryptedOpts) {
1777
1782
  const tceValue = typeof encryptedOpts.toolCallEvents === "string" ? encryptedOpts.toolCallEvents : JSON.stringify(encryptedOpts.toolCallEvents);
1778
1783
  msg._setRaw("tool_call_events", tceValue);
1779
1784
  }
1785
+ if (encryptedOpts.origin) msg._setRaw("origin", encryptedOpts.origin);
1780
1786
  }
1781
1787
  async function createMessageOp(ctx, opts) {
1782
1788
  if (opts.uniqueId) {
@@ -2119,7 +2125,8 @@ function makeSyntheticStoredMessage(opts) {
2119
2125
  thoughtProcess: opts.thoughtProcess,
2120
2126
  thinking: opts.thinking,
2121
2127
  parentMessageId: opts.parentMessageId,
2122
- toolCallEvents: opts.toolCallEvents
2128
+ toolCallEvents: opts.toolCallEvents,
2129
+ origin: opts.origin
2123
2130
  };
2124
2131
  }
2125
2132
  function makeSyntheticStoredConversation(opts, defaultTitle) {
@@ -3427,6 +3434,9 @@ async function embedMessage(ctx, messageId, options) {
3427
3434
  if (message.vector && message.vector.length > 0) {
3428
3435
  return message;
3429
3436
  }
3437
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
3438
+ return message;
3439
+ }
3430
3440
  const embedding = await generateEmbedding(message.content, options);
3431
3441
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
3432
3442
  return updateMessageEmbeddingOp(ctx, messageId, embedding, embeddingModel);
@@ -3448,6 +3458,9 @@ async function embedAllMessages(ctx, options, filter) {
3448
3458
  if (message.role === "system") {
3449
3459
  continue;
3450
3460
  }
3461
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
3462
+ continue;
3463
+ }
3451
3464
  const minLength = filter?.minContentLength ?? DEFAULT_MIN_CONTENT_LENGTH;
3452
3465
  if (message.content.length < minLength) {
3453
3466
  continue;
@@ -3473,6 +3486,9 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
3473
3486
  if (message.chunks && message.chunks.length > 0) {
3474
3487
  return message;
3475
3488
  }
3489
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
3490
+ return message;
3491
+ }
3476
3492
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
3477
3493
  if (!shouldChunkMessage(message.content, chunkSize)) {
3478
3494
  const embedding = await generateEmbedding(message.content, options);
@@ -3506,6 +3522,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
3506
3522
  if (hasVector && !filter?.rechunkExisting && !isStale) continue;
3507
3523
  if (filter?.roles && !filter.roles.includes(message.role)) continue;
3508
3524
  if (message.role === "system") continue;
3525
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) continue;
3509
3526
  if (message.content.length < minLength) continue;
3510
3527
  if (shouldChunkMessage(message.content, chunkSize)) {
3511
3528
  longMessages.push({
@@ -3562,7 +3579,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
3562
3579
  }
3563
3580
  return embeddedCount;
3564
3581
  }
3565
- var DEFAULT_MIN_CONTENT_LENGTH;
3582
+ var DEFAULT_MIN_CONTENT_LENGTH, NON_EMBEDDABLE_ORIGIN;
3566
3583
  var init_embeddings = __esm({
3567
3584
  "src/lib/memoryEngine/embeddings.ts"() {
3568
3585
  "use strict";
@@ -3573,6 +3590,7 @@ var init_embeddings = __esm({
3573
3590
  init_generate();
3574
3591
  init_generate();
3575
3592
  DEFAULT_MIN_CONTENT_LENGTH = 10;
3593
+ NON_EMBEDDABLE_ORIGIN = "tool_result";
3576
3594
  }
3577
3595
  });
3578
3596
 
@@ -4645,6 +4663,27 @@ var init_encryption2 = __esm({
4645
4663
  }
4646
4664
  });
4647
4665
 
4666
+ // src/lib/db/memoryVault/types.ts
4667
+ function parseMedia(value) {
4668
+ if (typeof value !== "string" || value === "") return null;
4669
+ try {
4670
+ const parsed = JSON.parse(value);
4671
+ if (!Array.isArray(parsed)) return null;
4672
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
4673
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
4674
+ objectKey: r.objectKey ?? r.object_key ?? null
4675
+ })).filter((r) => Number.isFinite(r.feedItemId));
4676
+ return refs.length > 0 ? refs : null;
4677
+ } catch {
4678
+ return null;
4679
+ }
4680
+ }
4681
+ var init_types4 = __esm({
4682
+ "src/lib/db/memoryVault/types.ts"() {
4683
+ "use strict";
4684
+ }
4685
+ });
4686
+
4648
4687
  // src/lib/db/memoryVault/operations.ts
4649
4688
  function visibilityOrPrivate(value) {
4650
4689
  return value === "public" ? value : "private";
@@ -4706,6 +4745,7 @@ function vaultMemoryToStoredRaw(memory) {
4706
4745
  sourceChunkIds,
4707
4746
  proofCount: memory.proofCount ?? null,
4708
4747
  source: memory.source ?? null,
4748
+ media: parseMedia(memory.media),
4709
4749
  eventTimeStart: memory.eventTimeStart ?? null,
4710
4750
  eventTimeEnd: memory.eventTimeEnd ?? null,
4711
4751
  eventTimeKind: memory.eventTimeKind ?? null,
@@ -4988,6 +5028,7 @@ function vaultMemoryRawToStoredRaw(raw) {
4988
5028
  eventTimeKind: raw.event_time_kind ?? null,
4989
5029
  // SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
4990
5030
  topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
5031
+ media: parseMedia(raw.media),
4991
5032
  topics: parseTopics(raw.topics),
4992
5033
  topicsUpdatedAt: raw.topics_updated_at ?? null,
4993
5034
  topicsExtractedAt: raw.topics_extracted_at ?? null,
@@ -5712,6 +5753,7 @@ var init_operations3 = __esm({
5712
5753
  init_operations2();
5713
5754
  init_types3();
5714
5755
  init_encryption2();
5756
+ init_types4();
5715
5757
  NON_PRIVATE_VISIBILITIES = ["public"];
5716
5758
  KNOWN_TRUST_TIERS = /* @__PURE__ */ new Set(["quarantined", "trusted"]);
5717
5759
  TOPICS_EXTRACTION_VERSION = 3;
@@ -6039,17 +6081,17 @@ function recencyMultiplier(updatedAt, opts = {}) {
6039
6081
  const now = opts.now ?? /* @__PURE__ */ new Date();
6040
6082
  const nowMs2 = now.getTime();
6041
6083
  if (!Number.isFinite(nowMs2)) return noDate;
6042
- const ageDays2 = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
6084
+ const ageDays2 = Math.max(0, (nowMs2 - updatedMs) / DAY_MS2);
6043
6085
  const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
6044
6086
  const floor = opts.floor ?? DEFAULT_FLOOR;
6045
6087
  const decay = perYearDecay * (ageDays2 / 365);
6046
6088
  return Math.max(floor, 1 - decay);
6047
6089
  }
6048
- var DAY_MS, DEFAULT_PER_YEAR_DECAY, DEFAULT_FLOOR, DEFAULT_NO_DATE_MULTIPLIER;
6090
+ var DAY_MS2, DEFAULT_PER_YEAR_DECAY, DEFAULT_FLOOR, DEFAULT_NO_DATE_MULTIPLIER;
6049
6091
  var init_recency = __esm({
6050
6092
  "src/lib/memory/recency.ts"() {
6051
6093
  "use strict";
6052
- DAY_MS = 1e3 * 60 * 60 * 24;
6094
+ DAY_MS2 = 1e3 * 60 * 60 * 24;
6053
6095
  DEFAULT_PER_YEAR_DECAY = 0.2;
6054
6096
  DEFAULT_FLOOR = 0.1;
6055
6097
  DEFAULT_NO_DATE_MULTIPLIER = 0.5;
@@ -6806,8 +6848,8 @@ function classifyObservationTrend(input, now = Date.now()) {
6806
6848
  const lastMsRaw = input.lastObservedAt;
6807
6849
  const lastMs = lastMsRaw !== null && lastMsRaw !== void 0 && Number.isFinite(lastMsRaw) ? Math.max(createdMs, lastMsRaw) : createdMs;
6808
6850
  const proofs = Math.max(1, input.proofCount ?? 1);
6809
- const ageDays2 = Math.max(0, (now - createdMs) / DAY_MS2);
6810
- const daysSinceLast = Math.max(0, (now - lastMs) / DAY_MS2);
6851
+ const ageDays2 = Math.max(0, (now - createdMs) / DAY_MS3);
6852
+ const daysSinceLast = Math.max(0, (now - lastMs) / DAY_MS3);
6811
6853
  if (daysSinceLast >= TREND_STALE_WINDOW_DAYS) return "stale";
6812
6854
  if (daysSinceLast >= TREND_RECENT_WINDOW_DAYS) return "weakening";
6813
6855
  if (ageDays2 <= TREND_RECENT_WINDOW_DAYS && proofs <= 2) return "new";
@@ -6828,11 +6870,11 @@ function summarizeObservationTrends(inputs, now = Date.now()) {
6828
6870
  }
6829
6871
  return counts;
6830
6872
  }
6831
- var DAY_MS2, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS;
6873
+ var DAY_MS3, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS;
6832
6874
  var init_observationTrend = __esm({
6833
6875
  "src/lib/memory/observationTrend.ts"() {
6834
6876
  "use strict";
6835
- DAY_MS2 = 1e3 * 60 * 60 * 24;
6877
+ DAY_MS3 = 1e3 * 60 * 60 * 24;
6836
6878
  TREND_RECENT_WINDOW_DAYS = 30;
6837
6879
  TREND_STALE_WINDOW_DAYS = 90;
6838
6880
  }
@@ -9115,12 +9157,14 @@ __export(index_exports, {
9115
9157
  getVaultMemoryOp: () => getVaultMemoryOp,
9116
9158
  hardDeleteDecayedOp: () => hardDeleteDecayedOp,
9117
9159
  hasEncryptionKey: () => hasEncryptionKey,
9160
+ ingestPublishedPhotoMemoriesOp: () => ingestPublishedPhotoMemoriesOp,
9118
9161
  injectionSignatureCatalog: () => injectionSignatureCatalog,
9119
9162
  isPiiRedactor: () => isPiiRedactor,
9120
9163
  isRerankerAvailable: () => isRerankerAvailable,
9121
9164
  moveMemoriesToFolderOp: () => moveMemoriesToFolderOp,
9122
9165
  noopLogger: () => noopLogger,
9123
9166
  onKeyAvailable: () => onKeyAvailable,
9167
+ parseMedia: () => parseMedia,
9124
9168
  preEmbedVaultMemories: () => preEmbedVaultMemories,
9125
9169
  quantizeEmbedding: () => quantizeEmbedding,
9126
9170
  queueManager: () => queueManager,
@@ -14193,6 +14237,9 @@ __decorateClass([
14193
14237
  __decorateClass([
14194
14238
  (0, import_decorators.json)("tool_call_events", (raw) => raw)
14195
14239
  ], Message.prototype, "toolCallEvents", 2);
14240
+ __decorateClass([
14241
+ (0, import_decorators.text)("origin")
14242
+ ], Message.prototype, "origin", 2);
14196
14243
  var Conversation = class extends import_watermelondb3.Model {
14197
14244
  };
14198
14245
  Conversation.table = "conversations";
@@ -14709,6 +14756,9 @@ __decorateClass([
14709
14756
  __decorateClass([
14710
14757
  (0, import_decorators3.field)("topics_updated_at")
14711
14758
  ], VaultMemory.prototype, "topicsUpdatedAt", 2);
14759
+ __decorateClass([
14760
+ (0, import_decorators3.field)("media")
14761
+ ], VaultMemory.prototype, "media", 2);
14712
14762
  __decorateClass([
14713
14763
  (0, import_decorators3.field)("topics_extracted_at")
14714
14764
  ], VaultMemory.prototype, "topicsExtractedAt", 2);
@@ -14759,6 +14809,138 @@ __decorateClass([
14759
14809
  // src/lib/db/memoryVault/index.ts
14760
14810
  init_operations3();
14761
14811
 
14812
+ // src/lib/memory/decay.ts
14813
+ init_logger();
14814
+ var DAY_MS = 24 * 60 * 60 * 1e3;
14815
+ var SHORT_TTL_MS = 30 * DAY_MS;
14816
+ var MEDIUM_TTL_MS = 180 * DAY_MS;
14817
+ var SOURCE_PHOTO = "photo";
14818
+ var NEVER_TTL_MS = Number.POSITIVE_INFINITY;
14819
+ var HARD_DELETE_WINDOW_MS = 30 * DAY_MS;
14820
+ var PAST_EVENT_GRACE_MS = 7 * DAY_MS;
14821
+ var DEFAULT_DECAY_POLICY = {
14822
+ ttlByType: {
14823
+ identity: NEVER_TTL_MS,
14824
+ preference: NEVER_TTL_MS,
14825
+ relationship: NEVER_TTL_MS,
14826
+ constraint: NEVER_TTL_MS,
14827
+ plan: SHORT_TTL_MS,
14828
+ ongoing_context: SHORT_TTL_MS,
14829
+ other: MEDIUM_TTL_MS
14830
+ },
14831
+ fallbackTtlMs: MEDIUM_TTL_MS,
14832
+ hardDeleteWindowMs: HARD_DELETE_WINDOW_MS,
14833
+ pastEventGraceMs: PAST_EVENT_GRACE_MS
14834
+ };
14835
+ function resolvePolicy(policy) {
14836
+ if (!policy) return DEFAULT_DECAY_POLICY;
14837
+ return {
14838
+ ttlByType: { ...DEFAULT_DECAY_POLICY.ttlByType, ...policy.ttlByType },
14839
+ fallbackTtlMs: policy.fallbackTtlMs ?? DEFAULT_DECAY_POLICY.fallbackTtlMs,
14840
+ hardDeleteWindowMs: policy.hardDeleteWindowMs ?? DEFAULT_DECAY_POLICY.hardDeleteWindowMs,
14841
+ pastEventGraceMs: policy.pastEventGraceMs ?? DEFAULT_DECAY_POLICY.pastEventGraceMs
14842
+ };
14843
+ }
14844
+ function ttlForType(factType, policy) {
14845
+ const resolved = resolvePolicy(policy);
14846
+ if (factType === null) return resolved.fallbackTtlMs;
14847
+ return resolved.ttlByType[factType] ?? resolved.fallbackTtlMs;
14848
+ }
14849
+ function isTimeSensitiveType(factType) {
14850
+ return factType === "plan" || factType === "ongoing_context";
14851
+ }
14852
+ function hasFiniteTimestamps(m, now) {
14853
+ return Number.isFinite(now) && Number.isFinite(m.updatedAt) && (m.archivedAt === null || Number.isFinite(m.archivedAt));
14854
+ }
14855
+ function classifyDecay(m, now, policy) {
14856
+ const resolved = resolvePolicy(policy);
14857
+ if (!hasFiniteTimestamps(m, now)) {
14858
+ getLogger().warn("[memory/decay] non-finite timestamp on a memory row; keeping it", {
14859
+ now,
14860
+ updatedAt: m.updatedAt,
14861
+ archivedAt: m.archivedAt,
14862
+ factType: m.factType
14863
+ });
14864
+ return "keep";
14865
+ }
14866
+ if (m.archivedAt !== null) {
14867
+ return now - m.archivedAt > resolved.hardDeleteWindowMs ? "delete" : "keep";
14868
+ }
14869
+ if (m.source === "manual" || m.source === SOURCE_PHOTO) return "keep";
14870
+ if (isTimeSensitiveType(m.factType) && m.eventTimeEnd !== null) {
14871
+ if (m.eventTimeEnd < now - resolved.pastEventGraceMs) return "archive";
14872
+ if (m.eventTimeEnd >= now) return "keep";
14873
+ }
14874
+ if (now - m.updatedAt > ttlForType(m.factType, resolved)) return "archive";
14875
+ return "keep";
14876
+ }
14877
+
14878
+ // src/lib/db/memoryVault/photoIngest.ts
14879
+ init_encryption2();
14880
+ var PHOTO_MEMORY_ID_PREFIX = "photo:";
14881
+ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
14882
+ const byId = /* @__PURE__ */ new Map();
14883
+ for (const r of rows) {
14884
+ if (typeof r.memoryId !== "string" || !r.memoryId.startsWith(PHOTO_MEMORY_ID_PREFIX)) continue;
14885
+ if (!byId.has(r.memoryId)) byId.set(r.memoryId, r);
14886
+ }
14887
+ const photoRows = [...byId.values()];
14888
+ if (photoRows.length === 0) return { inserted: 0, skipped: 0 };
14889
+ const known = await ctx.vaultMemoryCollection.query().fetchIds().then((ids) => new Set(ids));
14890
+ const candidates = photoRows.filter((r) => !known.has(r.memoryId));
14891
+ if (candidates.length === 0) return { inserted: 0, skipped: photoRows.length };
14892
+ const fresh = candidates;
14893
+ const contents = await Promise.all(
14894
+ fresh.map(async (r) => {
14895
+ if (ctx.walletAddress && ctx.signMessage) {
14896
+ return encryptVaultMemoryContent(
14897
+ r.text,
14898
+ ctx.walletAddress,
14899
+ ctx.signMessage,
14900
+ ctx.embeddedWalletSigner
14901
+ );
14902
+ }
14903
+ return r.text;
14904
+ })
14905
+ );
14906
+ const now = Date.now();
14907
+ let inserted = 0;
14908
+ await ctx.database.write(async () => {
14909
+ const present = new Set(await ctx.vaultMemoryCollection.query().fetchIds());
14910
+ const writable = fresh.map((row, i) => ({ row, content: contents[i] })).filter(({ row }) => !present.has(row.memoryId));
14911
+ inserted = writable.length;
14912
+ if (writable.length === 0) return;
14913
+ const prepared = writable.map(
14914
+ ({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record) => {
14915
+ record._raw.id = row.memoryId;
14916
+ record._setRaw("content", content);
14917
+ record._setRaw("scope", "private");
14918
+ record._setRaw("folder_id", null);
14919
+ record._setRaw("user_id", ctx.userId ?? null);
14920
+ record._setRaw("is_deleted", false);
14921
+ record._setRaw("proof_count", 1);
14922
+ record._setRaw("source", SOURCE_PHOTO);
14923
+ record._setRaw(
14924
+ "media",
14925
+ row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
14926
+ );
14927
+ record._setRaw("visibility", "public");
14928
+ record._setRaw("published_at", now);
14929
+ if (row.eventTime) {
14930
+ record._setRaw("event_time_start", row.eventTime.start ?? null);
14931
+ record._setRaw("event_time_end", row.eventTime.end ?? null);
14932
+ record._setRaw("event_time_kind", row.eventTime.kind ?? null);
14933
+ }
14934
+ })
14935
+ );
14936
+ await ctx.database.batch(...prepared);
14937
+ });
14938
+ return { inserted, skipped: photoRows.length - inserted };
14939
+ }
14940
+
14941
+ // src/lib/db/memoryVault/index.ts
14942
+ init_types4();
14943
+
14762
14944
  // src/lib/db/queue/manager.ts
14763
14945
  var import_uuid4 = require("uuid");
14764
14946
  init_logger();
@@ -16538,71 +16720,6 @@ function createChunkVectorCache(maxSize = DEFAULT_CHUNK_CACHE_SIZE) {
16538
16720
  return new LRUCache(maxSize);
16539
16721
  }
16540
16722
 
16541
- // src/lib/memory/decay.ts
16542
- init_logger();
16543
- var DAY_MS3 = 24 * 60 * 60 * 1e3;
16544
- var SHORT_TTL_MS = 30 * DAY_MS3;
16545
- var MEDIUM_TTL_MS = 180 * DAY_MS3;
16546
- var NEVER_TTL_MS = Number.POSITIVE_INFINITY;
16547
- var HARD_DELETE_WINDOW_MS = 30 * DAY_MS3;
16548
- var PAST_EVENT_GRACE_MS = 7 * DAY_MS3;
16549
- var DEFAULT_DECAY_POLICY = {
16550
- ttlByType: {
16551
- identity: NEVER_TTL_MS,
16552
- preference: NEVER_TTL_MS,
16553
- relationship: NEVER_TTL_MS,
16554
- constraint: NEVER_TTL_MS,
16555
- plan: SHORT_TTL_MS,
16556
- ongoing_context: SHORT_TTL_MS,
16557
- other: MEDIUM_TTL_MS
16558
- },
16559
- fallbackTtlMs: MEDIUM_TTL_MS,
16560
- hardDeleteWindowMs: HARD_DELETE_WINDOW_MS,
16561
- pastEventGraceMs: PAST_EVENT_GRACE_MS
16562
- };
16563
- function resolvePolicy(policy) {
16564
- if (!policy) return DEFAULT_DECAY_POLICY;
16565
- return {
16566
- ttlByType: { ...DEFAULT_DECAY_POLICY.ttlByType, ...policy.ttlByType },
16567
- fallbackTtlMs: policy.fallbackTtlMs ?? DEFAULT_DECAY_POLICY.fallbackTtlMs,
16568
- hardDeleteWindowMs: policy.hardDeleteWindowMs ?? DEFAULT_DECAY_POLICY.hardDeleteWindowMs,
16569
- pastEventGraceMs: policy.pastEventGraceMs ?? DEFAULT_DECAY_POLICY.pastEventGraceMs
16570
- };
16571
- }
16572
- function ttlForType(factType, policy) {
16573
- const resolved = resolvePolicy(policy);
16574
- if (factType === null) return resolved.fallbackTtlMs;
16575
- return resolved.ttlByType[factType] ?? resolved.fallbackTtlMs;
16576
- }
16577
- function isTimeSensitiveType(factType) {
16578
- return factType === "plan" || factType === "ongoing_context";
16579
- }
16580
- function hasFiniteTimestamps(m, now) {
16581
- return Number.isFinite(now) && Number.isFinite(m.updatedAt) && (m.archivedAt === null || Number.isFinite(m.archivedAt));
16582
- }
16583
- function classifyDecay(m, now, policy) {
16584
- const resolved = resolvePolicy(policy);
16585
- if (!hasFiniteTimestamps(m, now)) {
16586
- getLogger().warn("[memory/decay] non-finite timestamp on a memory row; keeping it", {
16587
- now,
16588
- updatedAt: m.updatedAt,
16589
- archivedAt: m.archivedAt,
16590
- factType: m.factType
16591
- });
16592
- return "keep";
16593
- }
16594
- if (m.archivedAt !== null) {
16595
- return now - m.archivedAt > resolved.hardDeleteWindowMs ? "delete" : "keep";
16596
- }
16597
- if (m.source === "manual") return "keep";
16598
- if (isTimeSensitiveType(m.factType) && m.eventTimeEnd !== null) {
16599
- if (m.eventTimeEnd < now - resolved.pastEventGraceMs) return "archive";
16600
- if (m.eventTimeEnd >= now) return "keep";
16601
- }
16602
- if (now - m.updatedAt > ttlForType(m.factType, resolved)) return "archive";
16603
- return "keep";
16604
- }
16605
-
16606
16723
  // src/lib/memory/decayClassifier.ts
16607
16724
  init_logger();
16608
16725
  init_redactor();
@@ -16705,7 +16822,7 @@ function toDecayInput(c) {
16705
16822
  };
16706
16823
  }
16707
16824
  function isBorderline(input) {
16708
- if (input.source === "manual") return false;
16825
+ if (input.source === "manual" || input.source === SOURCE_PHOTO) return false;
16709
16826
  if (input.trustTier === "quarantined") return false;
16710
16827
  if (input.archivedAt !== null) return false;
16711
16828
  if (input.factType === null || input.factType === "other") return true;
@@ -21427,7 +21544,7 @@ __decorateClass([
21427
21544
  ], VaultFolder.prototype, "context", 2);
21428
21545
 
21429
21546
  // src/lib/db/schema.ts
21430
- var SDK_SCHEMA_VERSION = 43;
21547
+ var SDK_SCHEMA_VERSION = 45;
21431
21548
  var sdkSchema = (0, import_watermelondb19.appSchema)({
21432
21549
  version: SDK_SCHEMA_VERSION,
21433
21550
  tables: [
@@ -21465,8 +21582,10 @@ var sdkSchema = (0, import_watermelondb19.appSchema)({
21465
21582
  // Parent message for branching
21466
21583
  { name: "feedback", type: "string", isOptional: true },
21467
21584
  // 'like' | 'dislike' | null
21468
- { name: "tool_call_events", type: "string", isOptional: true }
21585
+ { name: "tool_call_events", type: "string", isOptional: true },
21469
21586
  // JSON stringified LlmapiToolCallEvent[]
21587
+ { name: "origin", type: "string", isOptional: true }
21588
+ // MessageOrigin — provenance, NOT encrypted (see v44)
21470
21589
  ]
21471
21590
  }),
21472
21591
  (0, import_watermelondb19.tableSchema)({
@@ -21573,6 +21692,18 @@ var sdkSchema = (0, import_watermelondb19.appSchema)({
21573
21692
  // paths key on `updated_at` — so without this a topic-only change would
21574
21693
  // neither upload nor merge. Null = `topics` never written.
21575
21694
  { name: "topics_updated_at", type: "number", isOptional: true },
21695
+ // The photo(s) a SERVER-EXTRACTED memory was read out of, as a JSON
21696
+ // array of `{feed_item_id, object_key}` — exactly what
21697
+ // GET /api/memories/published returns in `media[]`. Enough to render the
21698
+ // source image without a second round-trip per memory.
21699
+ //
21700
+ // A JSON column rather than a join table: nothing on the client ever
21701
+ // queries BY photo (the only direction is memory -> render its image),
21702
+ // so a table would add a sync lane and a local-id space to serve a
21703
+ // question nobody asks. `topics` and `source_chunk_ids` set the
21704
+ // precedent for a list that is only ever read back whole. Null on
21705
+ // anything not extracted from a photo.
21706
+ { name: "media", type: "string", isOptional: true },
21576
21707
  // Unix ms of the last LLM topic-extraction pass over this memory's
21577
21708
  // content. Null = never extracted standalone (legacy rows with entity
21578
21709
  // links are grandfathered — see getMemoriesNeedingTopicExtractionOp).
@@ -22394,6 +22525,33 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
22394
22525
  "CREATE INDEX IF NOT EXISTS conversations_is_deleted_created_at ON conversations (is_deleted, created_at);"
22395
22526
  )
22396
22527
  ]
22528
+ },
22529
+ // v43 -> v44: Added origin column to history — the provenance tag the embedding
22530
+ // sweep reads to skip never-rendered tool-result rows. No backfill: NULL means
22531
+ // "legacy, provenance unknown" and keeps the pre-v44 behaviour of embedding the
22532
+ // row, so the only rows that stop being embedded are ones a v44+ producer tagged.
22533
+ {
22534
+ toVersion: 44,
22535
+ steps: [
22536
+ (0, import_migrations2.addColumns)({
22537
+ table: "history",
22538
+ columns: [{ name: "origin", type: "string", isOptional: true }]
22539
+ })
22540
+ ]
22541
+ },
22542
+ // v44 -> v45: `media` on memory_vault — the photo(s) a server-extracted
22543
+ // memory was read out of, as JSON `[{feed_item_id, object_key}]`, mirroring
22544
+ // the `media[]` that GET /api/memories/published already returns. Existing
22545
+ // rows keep NULL, which is the correct value for every memory that did not
22546
+ // come from a photo (i.e. all of them until photo ingest runs).
22547
+ {
22548
+ toVersion: 45,
22549
+ steps: [
22550
+ (0, import_migrations2.addColumns)({
22551
+ table: "memory_vault",
22552
+ columns: [{ name: "media", type: "string", isOptional: true }]
22553
+ })
22554
+ ]
22397
22555
  }
22398
22556
  ]
22399
22557
  });
@@ -23865,12 +24023,14 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
23865
24023
  getVaultMemoryOp,
23866
24024
  hardDeleteDecayedOp,
23867
24025
  hasEncryptionKey,
24026
+ ingestPublishedPhotoMemoriesOp,
23868
24027
  injectionSignatureCatalog,
23869
24028
  isPiiRedactor,
23870
24029
  isRerankerAvailable,
23871
24030
  moveMemoriesToFolderOp,
23872
24031
  noopLogger,
23873
24032
  onKeyAvailable,
24033
+ parseMedia,
23874
24034
  preEmbedVaultMemories,
23875
24035
  quantizeEmbedding,
23876
24036
  queueManager,