@anuma/sdk 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -79,7 +79,7 @@ import {
79
79
  updateVaultMemoryOp,
80
80
  upsertMessageOp,
81
81
  useEncryption
82
- } from "./chunk-PUKP5H4F.mjs";
82
+ } from "./chunk-3RXNQBS3.mjs";
83
83
  import {
84
84
  PII_PATTERNS,
85
85
  PiiRedactor,
@@ -4272,6 +4272,13 @@ function assembleMessagesWithHistory(historyMessages, callerMessages, summarySys
4272
4272
  ];
4273
4273
  }
4274
4274
 
4275
+ // src/lib/chat/imageParts.ts
4276
+ function isSendableImageURL(url) {
4277
+ if (!url) return false;
4278
+ const lower = url.toLowerCase();
4279
+ return lower.startsWith("http://") || lower.startsWith("https://") || lower.startsWith("data:image/");
4280
+ }
4281
+
4275
4282
  // src/lib/chat/sources.ts
4276
4283
  function extractSourcesFromToolCallEvents(toolCallEvents) {
4277
4284
  try {
@@ -5488,6 +5495,9 @@ __decorateClass([
5488
5495
  __decorateClass([
5489
5496
  field3("event_time_kind")
5490
5497
  ], VaultMemory.prototype, "eventTimeKind", 2);
5498
+ __decorateClass([
5499
+ field3("topics_user_managed")
5500
+ ], VaultMemory.prototype, "topicsUserManaged", 2);
5491
5501
  __decorateClass([
5492
5502
  readonly2,
5493
5503
  date3("created_at")
@@ -5838,6 +5848,9 @@ var WalletPoller = class {
5838
5848
  }
5839
5849
  };
5840
5850
 
5851
+ // src/lib/memory/autoExtract.ts
5852
+ import { Q as Q3 } from "@nozbe/watermelondb";
5853
+
5841
5854
  // src/lib/memory/retain.ts
5842
5855
  var DEFAULT_AUTO_MERGE_THRESHOLD = 0.85;
5843
5856
  var DEFAULT_SCOPE = "private";
@@ -5885,12 +5898,15 @@ async function retain(content, ctx, options = {}) {
5885
5898
  preserveUpdatedAt: true,
5886
5899
  ...eventTimeUpdate && { eventTime: eventTimeUpdate }
5887
5900
  });
5888
- return {
5889
- action: "merge",
5890
- memoryId: targetId,
5891
- targetId,
5892
- proofCount: updated?.proofCount ?? (existing.proofCount ?? 1) + 1
5893
- };
5901
+ if (updated) {
5902
+ return {
5903
+ action: "merge",
5904
+ memoryId: targetId,
5905
+ targetId,
5906
+ proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
5907
+ };
5908
+ }
5909
+ await assertMergeTargetGoneOrThrow(ctx, targetId);
5894
5910
  }
5895
5911
  }
5896
5912
  }
@@ -5973,11 +5989,15 @@ async function tryConsolidate(trimmed, ctx, options) {
5973
5989
  preserveUpdatedAt: true,
5974
5990
  ...eventTimeUpdate && { eventTime: eventTimeUpdate }
5975
5991
  });
5992
+ if (!updated) {
5993
+ await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
5994
+ return null;
5995
+ }
5976
5996
  return {
5977
5997
  action: "merge",
5978
5998
  memoryId: decision.targetId,
5979
5999
  targetId: decision.targetId,
5980
- proofCount: updated?.proofCount ?? (existing.proofCount ?? 1) + 1
6000
+ proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
5981
6001
  };
5982
6002
  }
5983
6003
  if (decision.action === "update" && decision.targetId && decision.content) {
@@ -6004,17 +6024,35 @@ async function tryConsolidate(trimmed, ctx, options) {
6004
6024
  preserveUpdatedAt: true,
6005
6025
  ...eventTimeUpdate && { eventTime: eventTimeUpdate }
6006
6026
  });
6027
+ if (!updated) {
6028
+ await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
6029
+ return null;
6030
+ }
6007
6031
  return {
6008
6032
  action: "update",
6009
6033
  memoryId: decision.targetId,
6010
6034
  targetId: decision.targetId,
6011
- proofCount: updated?.proofCount ?? (existing.proofCount ?? 1) + 1
6035
+ proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
6012
6036
  };
6013
6037
  }
6014
6038
  return null;
6015
6039
  }
6040
+ async function assertMergeTargetGoneOrThrow(ctx, targetId) {
6041
+ const stillExists = await getVaultMemoryOp(ctx.vaultCtx, targetId);
6042
+ if (stillExists) {
6043
+ throw new Error(`retain: merge into memory ${targetId} failed to persist`);
6044
+ }
6045
+ }
6016
6046
 
6017
6047
  // src/lib/memory/autoExtract.ts
6048
+ async function isMemoryTopicsUserManaged(ctx, memoryId) {
6049
+ try {
6050
+ const rows = await ctx.database.get(VaultMemory.table).query(Q3.where("id", memoryId)).fetch();
6051
+ return rows[0]?.topicsUserManaged === true;
6052
+ } catch {
6053
+ return true;
6054
+ }
6055
+ }
6018
6056
  var DEFAULT_MODEL = "gpt-oss/gpt-oss-120b";
6019
6057
  var DEFAULT_MIN_CONFIDENCE = 0.7;
6020
6058
  var MAX_CONTENT_LENGTH = 200;
@@ -6173,7 +6211,9 @@ async function extractAndRetain(messages, retainCtx, options) {
6173
6211
  results.push(result);
6174
6212
  if (options.entityCtx && candidate.entities.length > 0) {
6175
6213
  try {
6176
- await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities);
6214
+ if (!await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
6215
+ await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities);
6216
+ }
6177
6217
  } catch (err) {
6178
6218
  log.warn("[memory/extract] linkMemoryEntitiesOp failed", err);
6179
6219
  }
@@ -7570,7 +7610,7 @@ function storedToLlmapiMessage(stored) {
7570
7610
  const content = [{ type: "text", text: stored.content }];
7571
7611
  if (stored.role !== "assistant" && stored.files?.length) {
7572
7612
  for (const file of stored.files) {
7573
- if (file.url) {
7613
+ if (isSendableImageURL(file.url)) {
7574
7614
  content.push({
7575
7615
  type: "image_url",
7576
7616
  image_url: { url: file.url }
@@ -9191,7 +9231,7 @@ __decorateClass([
9191
9231
  ], VaultFolder.prototype, "context", 2);
9192
9232
 
9193
9233
  // src/lib/db/schema.ts
9194
- var SDK_SCHEMA_VERSION = 33;
9234
+ var SDK_SCHEMA_VERSION = 34;
9195
9235
  var sdkSchema = appSchema2({
9196
9236
  version: SDK_SCHEMA_VERSION,
9197
9237
  tables: [
@@ -9308,7 +9348,11 @@ var sdkSchema = appSchema2({
9308
9348
  // (start set, end null + kind='ongoing'), or none (both null).
9309
9349
  { name: "event_time_start", type: "number", isOptional: true, isIndexed: true },
9310
9350
  { name: "event_time_end", type: "number", isOptional: true },
9311
- { name: "event_time_kind", type: "string", isOptional: true }
9351
+ { name: "event_time_kind", type: "string", isOptional: true },
9352
+ // When true, the user has manually set this memory's topics (entity
9353
+ // links). Auto-extraction then leaves its links alone — the user owns
9354
+ // them. Null/false = topics are auto-derived (default).
9355
+ { name: "topics_user_managed", type: "boolean", isOptional: true }
9312
9356
  ]
9313
9357
  }),
9314
9358
  // Entity table — canonical names extracted from auto-extraction (W5).
@@ -9867,6 +9911,18 @@ var sdkMigrations = schemaMigrations2({
9867
9911
  columns: [{ name: "embedding_model", type: "string", isOptional: true }]
9868
9912
  })
9869
9913
  ]
9914
+ },
9915
+ // v33 -> v34: user-managed topics. `topics_user_managed` marks a memory
9916
+ // whose entity links the user has taken manual control of, so
9917
+ // auto-extraction stops touching them.
9918
+ {
9919
+ toVersion: 34,
9920
+ steps: [
9921
+ addColumns2({
9922
+ table: "memory_vault",
9923
+ columns: [{ name: "topics_user_managed", type: "boolean", isOptional: true }]
9924
+ })
9925
+ ]
9870
9926
  }
9871
9927
  ]
9872
9928
  });
@@ -10035,7 +10091,7 @@ var DatabaseManager = class {
10035
10091
  };
10036
10092
 
10037
10093
  // src/lib/db/vaultFolders/operations.ts
10038
- import { Q as Q3 } from "@nozbe/watermelondb";
10094
+ import { Q as Q4 } from "@nozbe/watermelondb";
10039
10095
  function folderToStored(folder) {
10040
10096
  return {
10041
10097
  uniqueId: folder.id,
@@ -10060,7 +10116,7 @@ async function createVaultFolderOp(ctx, opts) {
10060
10116
  return folderToStored(created);
10061
10117
  }
10062
10118
  async function getAllVaultFoldersOp(ctx) {
10063
- const results = await ctx.vaultFolderCollection.query(Q3.where("is_deleted", false), Q3.sortBy("created_at", Q3.desc)).fetch();
10119
+ const results = await ctx.vaultFolderCollection.query(Q4.where("is_deleted", false), Q4.sortBy("created_at", Q4.desc)).fetch();
10064
10120
  return results.map(folderToStored);
10065
10121
  }
10066
10122
  async function updateVaultFolderOp(ctx, id, opts) {
@@ -10077,7 +10133,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
10077
10133
  })
10078
10134
  );
10079
10135
  if (scopeChanged) {
10080
- const memories = await ctx.vaultMemoryCollection.query(Q3.where("folder_id", id), Q3.where("is_deleted", false)).fetch();
10136
+ const memories = await ctx.vaultMemoryCollection.query(Q4.where("folder_id", id), Q4.where("is_deleted", false)).fetch();
10081
10137
  for (const memory of memories) {
10082
10138
  updates.push(
10083
10139
  memory.prepareUpdate((r) => {
@@ -10099,7 +10155,7 @@ async function deleteVaultFolderOp(ctx, id) {
10099
10155
  const record = await ctx.vaultFolderCollection.find(id);
10100
10156
  if (record.isDeleted) return false;
10101
10157
  await ctx.database.write(async () => {
10102
- const memories = await ctx.vaultMemoryCollection.query(Q3.where("folder_id", id), Q3.where("is_deleted", false)).fetch();
10158
+ const memories = await ctx.vaultMemoryCollection.query(Q4.where("folder_id", id), Q4.where("is_deleted", false)).fetch();
10103
10159
  const preparedMemories = memories.map(
10104
10160
  (memory) => memory.prepareUpdate((r) => {
10105
10161
  r._setRaw("folder_id", null);
@@ -10168,7 +10224,7 @@ async function updateVaultFolderContextOp(ctx, id, context) {
10168
10224
  }
10169
10225
  }
10170
10226
  async function getVaultFolderMemoryCountOp(ctx, folderId) {
10171
- return await ctx.vaultMemoryCollection.query(Q3.where("folder_id", folderId), Q3.where("is_deleted", false)).fetchCount();
10227
+ return await ctx.vaultMemoryCollection.query(Q4.where("folder_id", folderId), Q4.where("is_deleted", false)).fetchCount();
10172
10228
  }
10173
10229
 
10174
10230
  // src/lib/db/vaultFolders/defaults.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-PUKP5H4F.mjs";
3
+ } from "./chunk-3RXNQBS3.mjs";
4
4
  import "./chunk-DFVCS3QQ.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {
@@ -1953,6 +1953,7 @@ function vaultMemoryToStoredRaw(memory) {
1953
1953
  eventTimeStart: memory.eventTimeStart ?? null,
1954
1954
  eventTimeEnd: memory.eventTimeEnd ?? null,
1955
1955
  eventTimeKind: memory.eventTimeKind ?? null,
1956
+ topicsUserManaged: memory.topicsUserManaged ?? false,
1956
1957
  createdAt: memory.createdAt,
1957
1958
  updatedAt: memory.updatedAt,
1958
1959
  isDeleted: memory.isDeleted
@@ -2134,9 +2135,10 @@ function vaultMemoryRawToStoredRaw(raw) {
2134
2135
  eventTimeStart: raw.event_time_start ?? null,
2135
2136
  eventTimeEnd: raw.event_time_end ?? null,
2136
2137
  eventTimeKind: raw.event_time_kind ?? null,
2138
+ // SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
2139
+ topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
2137
2140
  createdAt: new Date(raw.created_at),
2138
2141
  updatedAt: new Date(raw.updated_at),
2139
- // SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
2140
2142
  isDeleted: raw.is_deleted === true || raw.is_deleted === 1
2141
2143
  };
2142
2144
  }
@@ -2220,6 +2222,9 @@ async function updateVaultMemoryOp(ctx, id, opts) {
2220
2222
  r._setRaw("event_time_end", opts.eventTime.end ?? null);
2221
2223
  r._setRaw("event_time_kind", opts.eventTime.kind ?? null);
2222
2224
  }
2225
+ if (opts.topicsUserManaged !== void 0) {
2226
+ r._setRaw("topics_user_managed", opts.topicsUserManaged);
2227
+ }
2223
2228
  if (opts.preserveUpdatedAt) {
2224
2229
  r._setRaw("updated_at", originalUpdatedAt);
2225
2230
  }
@@ -2236,6 +2241,59 @@ async function updateVaultMemoryOp(ctx, id, opts) {
2236
2241
  return null;
2237
2242
  }
2238
2243
  }
2244
+ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
2245
+ const entityCtx = ctx.entityCtx;
2246
+ if (!entityCtx) {
2247
+ throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
2248
+ }
2249
+ let record;
2250
+ try {
2251
+ record = await ctx.vaultMemoryCollection.find(memoryId);
2252
+ } catch {
2253
+ return null;
2254
+ }
2255
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
2256
+ let stale = false;
2257
+ const originalUpdatedAt = record.updatedAt.getTime();
2258
+ await ctx.database.write(async () => {
2259
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
2260
+ stale = true;
2261
+ return;
2262
+ }
2263
+ await record.update((r) => {
2264
+ r._setRaw("topics_user_managed", true);
2265
+ r._setRaw("updated_at", originalUpdatedAt);
2266
+ });
2267
+ });
2268
+ if (stale) return null;
2269
+ const linked = entities.length > 0 ? await linkMemoryEntitiesOp(entityCtx, memoryId, entities) : [];
2270
+ const keep = new Set(linked.map((e) => e.uniqueId));
2271
+ const existing = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", memoryId)).fetch();
2272
+ const staleLinks = existing.filter((l) => !keep.has(String(l.entityId)));
2273
+ if (staleLinks.length > 0) {
2274
+ await ctx.database.write(async () => {
2275
+ await ctx.database.batch(...staleLinks.map((l) => l.prepareDestroyPermanently()));
2276
+ });
2277
+ }
2278
+ return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
2279
+ }
2280
+ async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
2281
+ let record;
2282
+ try {
2283
+ record = await ctx.vaultMemoryCollection.find(memoryId);
2284
+ } catch {
2285
+ return false;
2286
+ }
2287
+ if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
2288
+ const originalUpdatedAt = record.updatedAt.getTime();
2289
+ await ctx.database.write(async () => {
2290
+ await record.update((r) => {
2291
+ r._setRaw("topics_user_managed", false);
2292
+ r._setRaw("updated_at", originalUpdatedAt);
2293
+ });
2294
+ });
2295
+ return true;
2296
+ }
2239
2297
  async function deleteVaultMemoryOp(ctx, id) {
2240
2298
  try {
2241
2299
  const record = await ctx.vaultMemoryCollection.find(id);
@@ -4936,7 +4994,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
4936
4994
  legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
4937
4995
  );
4938
4996
  }
4939
- const { recall: recall2 } = await import("./recall-YBC7YCNC.mjs");
4997
+ const { recall: recall2 } = await import("./recall-NQ6ANFYN.mjs");
4940
4998
  const result = await recall2(
4941
4999
  query,
4942
5000
  { vaultCtx, embeddingOptions, vaultCache: cache },
@@ -5582,6 +5640,8 @@ export {
5582
5640
  getAllVaultMemoriesOp,
5583
5641
  getAllVaultMemoryContentsOp,
5584
5642
  updateVaultMemoryOp,
5643
+ setMemoryEntitiesOp,
5644
+ clearMemoryTopicsOverrideOp,
5585
5645
  deleteVaultMemoryOp,
5586
5646
  getUnfiledVaultMemoriesOp,
5587
5647
  deleteAllVaultMemoriesForUserOp,