@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.
@@ -1609,7 +1609,8 @@ function messageToStoredRaw(message, projection) {
1609
1609
  thinking: message.thinking,
1610
1610
  parentMessageId: message.parentMessageId,
1611
1611
  feedback: message.feedback || null,
1612
- toolCallEvents: parseJsonField(toolCallEventsRaw)
1612
+ toolCallEvents: parseJsonField(toolCallEventsRaw),
1613
+ origin: message.origin
1613
1614
  };
1614
1615
  }
1615
1616
  async function messageToStored(message, walletAddress, signMessage, embeddedWalletSigner, projection) {
@@ -1670,7 +1671,11 @@ function messageRawToStoredRaw(raw, projection) {
1670
1671
  thinking: raw.thinking,
1671
1672
  parentMessageId: raw.parent_message_id,
1672
1673
  feedback: raw.feedback || null,
1673
- toolCallEvents: parseJsonField(raw.tool_call_events)
1674
+ toolCallEvents: parseJsonField(raw.tool_call_events),
1675
+ // Load-bearing on this path specifically: getMessagesOp reads raws, and it is
1676
+ // what the deferred embedding sweep iterates, so the provenance gate depends
1677
+ // on `origin` surviving the raw mapper as well as the Model one.
1678
+ origin: raw.origin
1674
1679
  };
1675
1680
  }
1676
1681
  async function messageRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner, projection) {
@@ -2016,6 +2021,7 @@ function applyMessageFields(msg, encryptedOpts) {
2016
2021
  const tceValue = typeof encryptedOpts.toolCallEvents === "string" ? encryptedOpts.toolCallEvents : JSON.stringify(encryptedOpts.toolCallEvents);
2017
2022
  msg._setRaw("tool_call_events", tceValue);
2018
2023
  }
2024
+ if (encryptedOpts.origin) msg._setRaw("origin", encryptedOpts.origin);
2019
2025
  }
2020
2026
  async function createMessageOp(ctx, opts) {
2021
2027
  if (opts.uniqueId) {
@@ -2411,7 +2417,8 @@ function makeSyntheticStoredMessage(opts) {
2411
2417
  thoughtProcess: opts.thoughtProcess,
2412
2418
  thinking: opts.thinking,
2413
2419
  parentMessageId: opts.parentMessageId,
2414
- toolCallEvents: opts.toolCallEvents
2420
+ toolCallEvents: opts.toolCallEvents,
2421
+ origin: opts.origin
2415
2422
  };
2416
2423
  }
2417
2424
  function makeSyntheticStoredConversation(opts, defaultTitle) {
@@ -3626,6 +3633,9 @@ async function embedMessage(ctx, messageId, options) {
3626
3633
  if (message.vector && message.vector.length > 0) {
3627
3634
  return message;
3628
3635
  }
3636
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
3637
+ return message;
3638
+ }
3629
3639
  const embedding = await generateEmbedding(message.content, options);
3630
3640
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
3631
3641
  return updateMessageEmbeddingOp(ctx, messageId, embedding, embeddingModel);
@@ -3647,6 +3657,9 @@ async function embedAllMessages(ctx, options, filter) {
3647
3657
  if (message.role === "system") {
3648
3658
  continue;
3649
3659
  }
3660
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
3661
+ continue;
3662
+ }
3650
3663
  const minLength = filter?.minContentLength ?? DEFAULT_MIN_CONTENT_LENGTH;
3651
3664
  if (message.content.length < minLength) {
3652
3665
  continue;
@@ -3672,6 +3685,9 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
3672
3685
  if (message.chunks && message.chunks.length > 0) {
3673
3686
  return message;
3674
3687
  }
3688
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) {
3689
+ return message;
3690
+ }
3675
3691
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
3676
3692
  if (!shouldChunkMessage(message.content, chunkSize)) {
3677
3693
  const embedding = await generateEmbedding(message.content, options);
@@ -3705,6 +3721,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
3705
3721
  if (hasVector && !filter?.rechunkExisting && !isStale) continue;
3706
3722
  if (filter?.roles && !filter.roles.includes(message.role)) continue;
3707
3723
  if (message.role === "system") continue;
3724
+ if (message.origin === NON_EMBEDDABLE_ORIGIN) continue;
3708
3725
  if (message.content.length < minLength) continue;
3709
3726
  if (shouldChunkMessage(message.content, chunkSize)) {
3710
3727
  longMessages.push({
@@ -3761,7 +3778,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
3761
3778
  }
3762
3779
  return embeddedCount;
3763
3780
  }
3764
- var DEFAULT_MIN_CONTENT_LENGTH;
3781
+ var DEFAULT_MIN_CONTENT_LENGTH, NON_EMBEDDABLE_ORIGIN;
3765
3782
  var init_embeddings = __esm({
3766
3783
  "src/lib/memoryEngine/embeddings.ts"() {
3767
3784
  "use strict";
@@ -3772,6 +3789,7 @@ var init_embeddings = __esm({
3772
3789
  init_generate();
3773
3790
  init_generate();
3774
3791
  DEFAULT_MIN_CONTENT_LENGTH = 10;
3792
+ NON_EMBEDDABLE_ORIGIN = "tool_result";
3775
3793
  }
3776
3794
  });
3777
3795
 
@@ -4866,6 +4884,27 @@ var init_encryption2 = __esm({
4866
4884
  }
4867
4885
  });
4868
4886
 
4887
+ // src/lib/db/memoryVault/types.ts
4888
+ function parseMedia(value) {
4889
+ if (typeof value !== "string" || value === "") return null;
4890
+ try {
4891
+ const parsed = JSON.parse(value);
4892
+ if (!Array.isArray(parsed)) return null;
4893
+ const refs = parsed.filter((r) => typeof r === "object" && r !== null).map((r) => ({
4894
+ feedItemId: Number(r.feedItemId ?? r.feed_item_id),
4895
+ objectKey: r.objectKey ?? r.object_key ?? null
4896
+ })).filter((r) => Number.isFinite(r.feedItemId));
4897
+ return refs.length > 0 ? refs : null;
4898
+ } catch {
4899
+ return null;
4900
+ }
4901
+ }
4902
+ var init_types4 = __esm({
4903
+ "src/lib/db/memoryVault/types.ts"() {
4904
+ "use strict";
4905
+ }
4906
+ });
4907
+
4869
4908
  // src/lib/db/memoryVault/operations.ts
4870
4909
  function visibilityOrPrivate(value) {
4871
4910
  return value === "public" ? value : "private";
@@ -4927,6 +4966,7 @@ function vaultMemoryToStoredRaw(memory) {
4927
4966
  sourceChunkIds,
4928
4967
  proofCount: memory.proofCount ?? null,
4929
4968
  source: memory.source ?? null,
4969
+ media: parseMedia(memory.media),
4930
4970
  eventTimeStart: memory.eventTimeStart ?? null,
4931
4971
  eventTimeEnd: memory.eventTimeEnd ?? null,
4932
4972
  eventTimeKind: memory.eventTimeKind ?? null,
@@ -5209,6 +5249,7 @@ function vaultMemoryRawToStoredRaw(raw) {
5209
5249
  eventTimeKind: raw.event_time_kind ?? null,
5210
5250
  // SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
5211
5251
  topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
5252
+ media: parseMedia(raw.media),
5212
5253
  topics: parseTopics(raw.topics),
5213
5254
  topicsUpdatedAt: raw.topics_updated_at ?? null,
5214
5255
  topicsExtractedAt: raw.topics_extracted_at ?? null,
@@ -5995,6 +6036,7 @@ var init_operations3 = __esm({
5995
6036
  init_operations2();
5996
6037
  init_types3();
5997
6038
  init_encryption2();
6039
+ init_types4();
5998
6040
  NON_PRIVATE_VISIBILITIES = ["public"];
5999
6041
  KNOWN_TRUST_TIERS = /* @__PURE__ */ new Set(["quarantined", "trusted"]);
6000
6042
  TOPICS_EXTRACTION_VERSION = 3;
@@ -6322,17 +6364,17 @@ function recencyMultiplier(updatedAt, opts = {}) {
6322
6364
  const now = opts.now ?? /* @__PURE__ */ new Date();
6323
6365
  const nowMs2 = now.getTime();
6324
6366
  if (!Number.isFinite(nowMs2)) return noDate;
6325
- const ageDays2 = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
6367
+ const ageDays2 = Math.max(0, (nowMs2 - updatedMs) / DAY_MS2);
6326
6368
  const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
6327
6369
  const floor = opts.floor ?? DEFAULT_FLOOR;
6328
6370
  const decay = perYearDecay * (ageDays2 / 365);
6329
6371
  return Math.max(floor, 1 - decay);
6330
6372
  }
6331
- var DAY_MS, DEFAULT_PER_YEAR_DECAY, DEFAULT_FLOOR, DEFAULT_NO_DATE_MULTIPLIER;
6373
+ var DAY_MS2, DEFAULT_PER_YEAR_DECAY, DEFAULT_FLOOR, DEFAULT_NO_DATE_MULTIPLIER;
6332
6374
  var init_recency = __esm({
6333
6375
  "src/lib/memory/recency.ts"() {
6334
6376
  "use strict";
6335
- DAY_MS = 1e3 * 60 * 60 * 24;
6377
+ DAY_MS2 = 1e3 * 60 * 60 * 24;
6336
6378
  DEFAULT_PER_YEAR_DECAY = 0.2;
6337
6379
  DEFAULT_FLOOR = 0.1;
6338
6380
  DEFAULT_NO_DATE_MULTIPLIER = 0.5;
@@ -7089,8 +7131,8 @@ function classifyObservationTrend(input, now = Date.now()) {
7089
7131
  const lastMsRaw = input.lastObservedAt;
7090
7132
  const lastMs = lastMsRaw !== null && lastMsRaw !== void 0 && Number.isFinite(lastMsRaw) ? Math.max(createdMs, lastMsRaw) : createdMs;
7091
7133
  const proofs = Math.max(1, input.proofCount ?? 1);
7092
- const ageDays2 = Math.max(0, (now - createdMs) / DAY_MS2);
7093
- const daysSinceLast = Math.max(0, (now - lastMs) / DAY_MS2);
7134
+ const ageDays2 = Math.max(0, (now - createdMs) / DAY_MS3);
7135
+ const daysSinceLast = Math.max(0, (now - lastMs) / DAY_MS3);
7094
7136
  if (daysSinceLast >= TREND_STALE_WINDOW_DAYS) return "stale";
7095
7137
  if (daysSinceLast >= TREND_RECENT_WINDOW_DAYS) return "weakening";
7096
7138
  if (ageDays2 <= TREND_RECENT_WINDOW_DAYS && proofs <= 2) return "new";
@@ -7111,11 +7153,11 @@ function summarizeObservationTrends(inputs, now = Date.now()) {
7111
7153
  }
7112
7154
  return counts;
7113
7155
  }
7114
- var DAY_MS2, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS;
7156
+ var DAY_MS3, TREND_RECENT_WINDOW_DAYS, TREND_STALE_WINDOW_DAYS;
7115
7157
  var init_observationTrend = __esm({
7116
7158
  "src/lib/memory/observationTrend.ts"() {
7117
7159
  "use strict";
7118
- DAY_MS2 = 1e3 * 60 * 60 * 24;
7160
+ DAY_MS3 = 1e3 * 60 * 60 * 24;
7119
7161
  TREND_RECENT_WINDOW_DAYS = 30;
7120
7162
  TREND_STALE_WINDOW_DAYS = 90;
7121
7163
  }
@@ -9563,6 +9605,7 @@ __export(index_exports, {
9563
9605
  hasICloudCredentials: () => hasICloudCredentials,
9564
9606
  hasKeyPair: () => hasKeyPair,
9565
9607
  hasNotionCredentials: () => hasNotionCredentials,
9608
+ ingestPublishedPhotoMemoriesOp: () => ingestPublishedPhotoMemoriesOp,
9566
9609
  injectionSignatureCatalog: () => injectionSignatureCatalog,
9567
9610
  insertAfterId: () => insertAfterId,
9568
9611
  insertChild: () => insertChild,
@@ -9589,6 +9632,7 @@ __export(index_exports, {
9589
9632
  noopLogger: () => noopLogger,
9590
9633
  onKeyAvailable: () => onKeyAvailable,
9591
9634
  parseJsx: () => parseJsx,
9635
+ parseMedia: () => parseMedia,
9592
9636
  preEmbedVaultMemories: () => preEmbedVaultMemories,
9593
9637
  preprocessFiles: () => preprocessFiles,
9594
9638
  previewToolSelection: () => previewToolSelection,
@@ -14888,6 +14932,43 @@ async function cleanupConversationSummary(database, conversationId) {
14888
14932
  }
14889
14933
  }
14890
14934
 
14935
+ // src/lib/chat/toolResultMessage.ts
14936
+ var HEADER = "[Tool Execution Results]\n\n";
14937
+ var FOOTER = "\n\nBased on these results, continue with the task.";
14938
+ var ENTRY_SEPARATOR = "\n\n";
14939
+ var MAX_PERSISTED_TOOL_RESULT_CHARS = 1e5;
14940
+ function buildToolResultContent(results) {
14941
+ const entries = results.map((r) => `Tool "${r.name}" returned: ${JSON.stringify(r.result)}`);
14942
+ const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0, entries.length - 1);
14943
+ const summary = capEntries(entries, MAX_PERSISTED_TOOL_RESULT_CHARS - framing).join(
14944
+ ENTRY_SEPARATOR
14945
+ );
14946
+ return `${HEADER}${summary}${FOOTER}`;
14947
+ }
14948
+ function capEntries(entries, budget) {
14949
+ const smallestFirst = entries.map((_, index) => index).sort((a, b) => entries[a].length - entries[b].length);
14950
+ const capped = [...entries];
14951
+ let remaining = budget;
14952
+ let unassigned = entries.length;
14953
+ for (const index of smallestFirst) {
14954
+ capped[index] = truncateEntry(entries[index], Math.floor(remaining / unassigned));
14955
+ remaining -= capped[index].length;
14956
+ unassigned--;
14957
+ }
14958
+ return capped;
14959
+ }
14960
+ function truncateEntry(entry, allowance) {
14961
+ if (entry.length <= allowance) return entry;
14962
+ const keep = allowance - truncationMarker(entry.length).length;
14963
+ if (keep <= 0) return entry.slice(0, Math.max(0, allowance));
14964
+ return `${entry.slice(0, keep)}${truncationMarker(entry.length - keep)}`;
14965
+ }
14966
+ function truncationMarker(omitted) {
14967
+ return `
14968
+
14969
+ ... (tool output truncated, ${omitted} characters omitted)`;
14970
+ }
14971
+
14891
14972
  // src/lib/db/chat/lazyDecrypt.ts
14892
14973
  init_useEncryption();
14893
14974
  init_encryption_utils();
@@ -15033,6 +15114,9 @@ __decorateClass([
15033
15114
  __decorateClass([
15034
15115
  (0, import_decorators.json)("tool_call_events", (raw) => raw)
15035
15116
  ], Message.prototype, "toolCallEvents", 2);
15117
+ __decorateClass([
15118
+ (0, import_decorators.text)("origin")
15119
+ ], Message.prototype, "origin", 2);
15036
15120
  var Conversation = class extends import_watermelondb3.Model {
15037
15121
  };
15038
15122
  Conversation.table = "conversations";
@@ -16348,6 +16432,9 @@ __decorateClass([
16348
16432
  __decorateClass([
16349
16433
  (0, import_decorators3.field)("topics_updated_at")
16350
16434
  ], VaultMemory.prototype, "topicsUpdatedAt", 2);
16435
+ __decorateClass([
16436
+ (0, import_decorators3.field)("media")
16437
+ ], VaultMemory.prototype, "media", 2);
16351
16438
  __decorateClass([
16352
16439
  (0, import_decorators3.field)("topics_extracted_at")
16353
16440
  ], VaultMemory.prototype, "topicsExtractedAt", 2);
@@ -16398,6 +16485,138 @@ __decorateClass([
16398
16485
  // src/lib/db/memoryVault/index.ts
16399
16486
  init_operations3();
16400
16487
 
16488
+ // src/lib/memory/decay.ts
16489
+ init_logger();
16490
+ var DAY_MS = 24 * 60 * 60 * 1e3;
16491
+ var SHORT_TTL_MS = 30 * DAY_MS;
16492
+ var MEDIUM_TTL_MS = 180 * DAY_MS;
16493
+ var SOURCE_PHOTO = "photo";
16494
+ var NEVER_TTL_MS = Number.POSITIVE_INFINITY;
16495
+ var HARD_DELETE_WINDOW_MS = 30 * DAY_MS;
16496
+ var PAST_EVENT_GRACE_MS = 7 * DAY_MS;
16497
+ var DEFAULT_DECAY_POLICY = {
16498
+ ttlByType: {
16499
+ identity: NEVER_TTL_MS,
16500
+ preference: NEVER_TTL_MS,
16501
+ relationship: NEVER_TTL_MS,
16502
+ constraint: NEVER_TTL_MS,
16503
+ plan: SHORT_TTL_MS,
16504
+ ongoing_context: SHORT_TTL_MS,
16505
+ other: MEDIUM_TTL_MS
16506
+ },
16507
+ fallbackTtlMs: MEDIUM_TTL_MS,
16508
+ hardDeleteWindowMs: HARD_DELETE_WINDOW_MS,
16509
+ pastEventGraceMs: PAST_EVENT_GRACE_MS
16510
+ };
16511
+ function resolvePolicy(policy) {
16512
+ if (!policy) return DEFAULT_DECAY_POLICY;
16513
+ return {
16514
+ ttlByType: { ...DEFAULT_DECAY_POLICY.ttlByType, ...policy.ttlByType },
16515
+ fallbackTtlMs: policy.fallbackTtlMs ?? DEFAULT_DECAY_POLICY.fallbackTtlMs,
16516
+ hardDeleteWindowMs: policy.hardDeleteWindowMs ?? DEFAULT_DECAY_POLICY.hardDeleteWindowMs,
16517
+ pastEventGraceMs: policy.pastEventGraceMs ?? DEFAULT_DECAY_POLICY.pastEventGraceMs
16518
+ };
16519
+ }
16520
+ function ttlForType(factType, policy) {
16521
+ const resolved = resolvePolicy(policy);
16522
+ if (factType === null) return resolved.fallbackTtlMs;
16523
+ return resolved.ttlByType[factType] ?? resolved.fallbackTtlMs;
16524
+ }
16525
+ function isTimeSensitiveType(factType) {
16526
+ return factType === "plan" || factType === "ongoing_context";
16527
+ }
16528
+ function hasFiniteTimestamps(m, now) {
16529
+ return Number.isFinite(now) && Number.isFinite(m.updatedAt) && (m.archivedAt === null || Number.isFinite(m.archivedAt));
16530
+ }
16531
+ function classifyDecay(m, now, policy) {
16532
+ const resolved = resolvePolicy(policy);
16533
+ if (!hasFiniteTimestamps(m, now)) {
16534
+ getLogger().warn("[memory/decay] non-finite timestamp on a memory row; keeping it", {
16535
+ now,
16536
+ updatedAt: m.updatedAt,
16537
+ archivedAt: m.archivedAt,
16538
+ factType: m.factType
16539
+ });
16540
+ return "keep";
16541
+ }
16542
+ if (m.archivedAt !== null) {
16543
+ return now - m.archivedAt > resolved.hardDeleteWindowMs ? "delete" : "keep";
16544
+ }
16545
+ if (m.source === "manual" || m.source === SOURCE_PHOTO) return "keep";
16546
+ if (isTimeSensitiveType(m.factType) && m.eventTimeEnd !== null) {
16547
+ if (m.eventTimeEnd < now - resolved.pastEventGraceMs) return "archive";
16548
+ if (m.eventTimeEnd >= now) return "keep";
16549
+ }
16550
+ if (now - m.updatedAt > ttlForType(m.factType, resolved)) return "archive";
16551
+ return "keep";
16552
+ }
16553
+
16554
+ // src/lib/db/memoryVault/photoIngest.ts
16555
+ init_encryption2();
16556
+ var PHOTO_MEMORY_ID_PREFIX = "photo:";
16557
+ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
16558
+ const byId = /* @__PURE__ */ new Map();
16559
+ for (const r of rows) {
16560
+ if (typeof r.memoryId !== "string" || !r.memoryId.startsWith(PHOTO_MEMORY_ID_PREFIX)) continue;
16561
+ if (!byId.has(r.memoryId)) byId.set(r.memoryId, r);
16562
+ }
16563
+ const photoRows = [...byId.values()];
16564
+ if (photoRows.length === 0) return { inserted: 0, skipped: 0 };
16565
+ const known = await ctx.vaultMemoryCollection.query().fetchIds().then((ids) => new Set(ids));
16566
+ const candidates = photoRows.filter((r) => !known.has(r.memoryId));
16567
+ if (candidates.length === 0) return { inserted: 0, skipped: photoRows.length };
16568
+ const fresh = candidates;
16569
+ const contents = await Promise.all(
16570
+ fresh.map(async (r) => {
16571
+ if (ctx.walletAddress && ctx.signMessage) {
16572
+ return encryptVaultMemoryContent(
16573
+ r.text,
16574
+ ctx.walletAddress,
16575
+ ctx.signMessage,
16576
+ ctx.embeddedWalletSigner
16577
+ );
16578
+ }
16579
+ return r.text;
16580
+ })
16581
+ );
16582
+ const now = Date.now();
16583
+ let inserted = 0;
16584
+ await ctx.database.write(async () => {
16585
+ const present = new Set(await ctx.vaultMemoryCollection.query().fetchIds());
16586
+ const writable = fresh.map((row, i) => ({ row, content: contents[i] })).filter(({ row }) => !present.has(row.memoryId));
16587
+ inserted = writable.length;
16588
+ if (writable.length === 0) return;
16589
+ const prepared = writable.map(
16590
+ ({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record) => {
16591
+ record._raw.id = row.memoryId;
16592
+ record._setRaw("content", content);
16593
+ record._setRaw("scope", "private");
16594
+ record._setRaw("folder_id", null);
16595
+ record._setRaw("user_id", ctx.userId ?? null);
16596
+ record._setRaw("is_deleted", false);
16597
+ record._setRaw("proof_count", 1);
16598
+ record._setRaw("source", SOURCE_PHOTO);
16599
+ record._setRaw(
16600
+ "media",
16601
+ row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
16602
+ );
16603
+ record._setRaw("visibility", "public");
16604
+ record._setRaw("published_at", now);
16605
+ if (row.eventTime) {
16606
+ record._setRaw("event_time_start", row.eventTime.start ?? null);
16607
+ record._setRaw("event_time_end", row.eventTime.end ?? null);
16608
+ record._setRaw("event_time_kind", row.eventTime.kind ?? null);
16609
+ }
16610
+ })
16611
+ );
16612
+ await ctx.database.batch(...prepared);
16613
+ });
16614
+ return { inserted, skipped: photoRows.length - inserted };
16615
+ }
16616
+
16617
+ // src/lib/db/memoryVault/index.ts
16618
+ init_types4();
16619
+
16401
16620
  // src/react/useChatStorage.ts
16402
16621
  init_logger();
16403
16622
 
@@ -17837,71 +18056,6 @@ function createChunkVectorCache(maxSize = DEFAULT_CHUNK_CACHE_SIZE) {
17837
18056
  return new LRUCache(maxSize);
17838
18057
  }
17839
18058
 
17840
- // src/lib/memory/decay.ts
17841
- init_logger();
17842
- var DAY_MS3 = 24 * 60 * 60 * 1e3;
17843
- var SHORT_TTL_MS = 30 * DAY_MS3;
17844
- var MEDIUM_TTL_MS = 180 * DAY_MS3;
17845
- var NEVER_TTL_MS = Number.POSITIVE_INFINITY;
17846
- var HARD_DELETE_WINDOW_MS = 30 * DAY_MS3;
17847
- var PAST_EVENT_GRACE_MS = 7 * DAY_MS3;
17848
- var DEFAULT_DECAY_POLICY = {
17849
- ttlByType: {
17850
- identity: NEVER_TTL_MS,
17851
- preference: NEVER_TTL_MS,
17852
- relationship: NEVER_TTL_MS,
17853
- constraint: NEVER_TTL_MS,
17854
- plan: SHORT_TTL_MS,
17855
- ongoing_context: SHORT_TTL_MS,
17856
- other: MEDIUM_TTL_MS
17857
- },
17858
- fallbackTtlMs: MEDIUM_TTL_MS,
17859
- hardDeleteWindowMs: HARD_DELETE_WINDOW_MS,
17860
- pastEventGraceMs: PAST_EVENT_GRACE_MS
17861
- };
17862
- function resolvePolicy(policy) {
17863
- if (!policy) return DEFAULT_DECAY_POLICY;
17864
- return {
17865
- ttlByType: { ...DEFAULT_DECAY_POLICY.ttlByType, ...policy.ttlByType },
17866
- fallbackTtlMs: policy.fallbackTtlMs ?? DEFAULT_DECAY_POLICY.fallbackTtlMs,
17867
- hardDeleteWindowMs: policy.hardDeleteWindowMs ?? DEFAULT_DECAY_POLICY.hardDeleteWindowMs,
17868
- pastEventGraceMs: policy.pastEventGraceMs ?? DEFAULT_DECAY_POLICY.pastEventGraceMs
17869
- };
17870
- }
17871
- function ttlForType(factType, policy) {
17872
- const resolved = resolvePolicy(policy);
17873
- if (factType === null) return resolved.fallbackTtlMs;
17874
- return resolved.ttlByType[factType] ?? resolved.fallbackTtlMs;
17875
- }
17876
- function isTimeSensitiveType(factType) {
17877
- return factType === "plan" || factType === "ongoing_context";
17878
- }
17879
- function hasFiniteTimestamps(m, now) {
17880
- return Number.isFinite(now) && Number.isFinite(m.updatedAt) && (m.archivedAt === null || Number.isFinite(m.archivedAt));
17881
- }
17882
- function classifyDecay(m, now, policy) {
17883
- const resolved = resolvePolicy(policy);
17884
- if (!hasFiniteTimestamps(m, now)) {
17885
- getLogger().warn("[memory/decay] non-finite timestamp on a memory row; keeping it", {
17886
- now,
17887
- updatedAt: m.updatedAt,
17888
- archivedAt: m.archivedAt,
17889
- factType: m.factType
17890
- });
17891
- return "keep";
17892
- }
17893
- if (m.archivedAt !== null) {
17894
- return now - m.archivedAt > resolved.hardDeleteWindowMs ? "delete" : "keep";
17895
- }
17896
- if (m.source === "manual") return "keep";
17897
- if (isTimeSensitiveType(m.factType) && m.eventTimeEnd !== null) {
17898
- if (m.eventTimeEnd < now - resolved.pastEventGraceMs) return "archive";
17899
- if (m.eventTimeEnd >= now) return "keep";
17900
- }
17901
- if (now - m.updatedAt > ttlForType(m.factType, resolved)) return "archive";
17902
- return "keep";
17903
- }
17904
-
17905
18059
  // src/lib/memory/decayClassifier.ts
17906
18060
  init_logger();
17907
18061
  init_redactor();
@@ -18004,7 +18158,7 @@ function toDecayInput(c) {
18004
18158
  };
18005
18159
  }
18006
18160
  function isBorderline(input) {
18007
- if (input.source === "manual") return false;
18161
+ if (input.source === "manual" || input.source === SOURCE_PHOTO) return false;
18008
18162
  if (input.trustTier === "quarantined") return false;
18009
18163
  if (input.archivedAt !== null) return false;
18010
18164
  if (input.factType === null || input.factType === "other") return true;
@@ -23664,12 +23818,7 @@ function useChatStorage(options) {
23664
23818
  }
23665
23819
  const autoToolResults = result.autoExecutedToolResults;
23666
23820
  if (autoToolResults && autoToolResults.length > 0) {
23667
- const toolSummary = autoToolResults.map((r) => `Tool "${r.name}" returned: ${JSON.stringify(r.result)}`).join("\n\n");
23668
- const toolResultContent = `[Tool Execution Results]
23669
-
23670
- ${toolSummary}
23671
-
23672
- Based on these results, continue with the task.`;
23821
+ const toolResultContent = buildToolResultContent(autoToolResults);
23673
23822
  try {
23674
23823
  await writeOrQueue(
23675
23824
  "createMessage",
@@ -23678,21 +23827,24 @@ Based on these results, continue with the task.`;
23678
23827
  role: "user",
23679
23828
  content: toolResultContent,
23680
23829
  model: "",
23681
- parentMessageId: storedAssistantMessage.uniqueId
23830
+ parentMessageId: storedAssistantMessage.uniqueId,
23831
+ origin: "tool_result"
23682
23832
  },
23683
23833
  () => createMessageOp(storageCtx, {
23684
23834
  conversationId: convId,
23685
23835
  role: "user",
23686
23836
  content: toolResultContent,
23687
23837
  model: "",
23688
- parentMessageId: storedAssistantMessage.uniqueId
23838
+ parentMessageId: storedAssistantMessage.uniqueId,
23839
+ origin: "tool_result"
23689
23840
  }),
23690
23841
  () => makeSyntheticStoredMessage({
23691
23842
  conversationId: convId,
23692
23843
  role: "user",
23693
23844
  content: toolResultContent,
23694
23845
  model: "",
23695
- parentMessageId: storedAssistantMessage.uniqueId
23846
+ parentMessageId: storedAssistantMessage.uniqueId,
23847
+ origin: "tool_result"
23696
23848
  }),
23697
23849
  assistantMsgQueueId ? [assistantMsgQueueId] : []
23698
23850
  );
@@ -24000,7 +24152,7 @@ __decorateClass([
24000
24152
  ], VaultFolder.prototype, "context", 2);
24001
24153
 
24002
24154
  // src/lib/db/schema.ts
24003
- var SDK_SCHEMA_VERSION = 43;
24155
+ var SDK_SCHEMA_VERSION = 45;
24004
24156
  var sdkSchema = (0, import_watermelondb20.appSchema)({
24005
24157
  version: SDK_SCHEMA_VERSION,
24006
24158
  tables: [
@@ -24038,8 +24190,10 @@ var sdkSchema = (0, import_watermelondb20.appSchema)({
24038
24190
  // Parent message for branching
24039
24191
  { name: "feedback", type: "string", isOptional: true },
24040
24192
  // 'like' | 'dislike' | null
24041
- { name: "tool_call_events", type: "string", isOptional: true }
24193
+ { name: "tool_call_events", type: "string", isOptional: true },
24042
24194
  // JSON stringified LlmapiToolCallEvent[]
24195
+ { name: "origin", type: "string", isOptional: true }
24196
+ // MessageOrigin — provenance, NOT encrypted (see v44)
24043
24197
  ]
24044
24198
  }),
24045
24199
  (0, import_watermelondb20.tableSchema)({
@@ -24146,6 +24300,18 @@ var sdkSchema = (0, import_watermelondb20.appSchema)({
24146
24300
  // paths key on `updated_at` — so without this a topic-only change would
24147
24301
  // neither upload nor merge. Null = `topics` never written.
24148
24302
  { name: "topics_updated_at", type: "number", isOptional: true },
24303
+ // The photo(s) a SERVER-EXTRACTED memory was read out of, as a JSON
24304
+ // array of `{feed_item_id, object_key}` — exactly what
24305
+ // GET /api/memories/published returns in `media[]`. Enough to render the
24306
+ // source image without a second round-trip per memory.
24307
+ //
24308
+ // A JSON column rather than a join table: nothing on the client ever
24309
+ // queries BY photo (the only direction is memory -> render its image),
24310
+ // so a table would add a sync lane and a local-id space to serve a
24311
+ // question nobody asks. `topics` and `source_chunk_ids` set the
24312
+ // precedent for a list that is only ever read back whole. Null on
24313
+ // anything not extracted from a photo.
24314
+ { name: "media", type: "string", isOptional: true },
24149
24315
  // Unix ms of the last LLM topic-extraction pass over this memory's
24150
24316
  // content. Null = never extracted standalone (legacy rows with entity
24151
24317
  // links are grandfathered — see getMemoriesNeedingTopicExtractionOp).
@@ -24967,6 +25133,33 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
24967
25133
  "CREATE INDEX IF NOT EXISTS conversations_is_deleted_created_at ON conversations (is_deleted, created_at);"
24968
25134
  )
24969
25135
  ]
25136
+ },
25137
+ // v43 -> v44: Added origin column to history — the provenance tag the embedding
25138
+ // sweep reads to skip never-rendered tool-result rows. No backfill: NULL means
25139
+ // "legacy, provenance unknown" and keeps the pre-v44 behaviour of embedding the
25140
+ // row, so the only rows that stop being embedded are ones a v44+ producer tagged.
25141
+ {
25142
+ toVersion: 44,
25143
+ steps: [
25144
+ (0, import_migrations2.addColumns)({
25145
+ table: "history",
25146
+ columns: [{ name: "origin", type: "string", isOptional: true }]
25147
+ })
25148
+ ]
25149
+ },
25150
+ // v44 -> v45: `media` on memory_vault — the photo(s) a server-extracted
25151
+ // memory was read out of, as JSON `[{feed_item_id, object_key}]`, mirroring
25152
+ // the `media[]` that GET /api/memories/published already returns. Existing
25153
+ // rows keep NULL, which is the correct value for every memory that did not
25154
+ // come from a photo (i.e. all of them until photo ingest runs).
25155
+ {
25156
+ toVersion: 45,
25157
+ steps: [
25158
+ (0, import_migrations2.addColumns)({
25159
+ table: "memory_vault",
25160
+ columns: [{ name: "media", type: "string", isOptional: true }]
25161
+ })
25162
+ ]
24970
25163
  }
24971
25164
  ]
24972
25165
  });
@@ -33120,7 +33313,7 @@ IMPORTANT: For write operations (POST, PUT, PATCH, DELETE), always confirm with
33120
33313
  }
33121
33314
  try {
33122
33315
  const data = JSON.parse(text12);
33123
- const json4 = JSON.stringify(data, null, 2);
33316
+ const json4 = JSON.stringify(data);
33124
33317
  return truncate(json4, MAX_RESPONSE_SIZE);
33125
33318
  } catch {
33126
33319
  return truncate(text12, MAX_RESPONSE_SIZE);
@@ -34868,6 +35061,7 @@ function renderAnumaJsx(jsx3) {
34868
35061
  hasICloudCredentials,
34869
35062
  hasKeyPair,
34870
35063
  hasNotionCredentials,
35064
+ ingestPublishedPhotoMemoriesOp,
34871
35065
  injectionSignatureCatalog,
34872
35066
  insertAfterId,
34873
35067
  insertChild,
@@ -34894,6 +35088,7 @@ function renderAnumaJsx(jsx3) {
34894
35088
  noopLogger,
34895
35089
  onKeyAvailable,
34896
35090
  parseJsx,
35091
+ parseMedia,
34897
35092
  preEmbedVaultMemories,
34898
35093
  preprocessFiles,
34899
35094
  previewToolSelection,