@anuma/sdk 6.32.0 → 6.33.1

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.
@@ -7677,7 +7677,13 @@ async function runToolLoop(options) {
7677
7677
  );
7678
7678
  const extra = results.flatMap((r) => Array.isArray(r) ? r : []);
7679
7679
  if (extra.length > 0) {
7680
- messages = [...messages, ...await redactBatch(extra)];
7680
+ let userIndex = messages.length - 1;
7681
+ while (userIndex > 0 && messages[userIndex].role !== "user") userIndex--;
7682
+ messages = [
7683
+ ...messages.slice(0, userIndex),
7684
+ ...await redactBatch(extra),
7685
+ ...messages.slice(userIndex)
7686
+ ];
7681
7687
  }
7682
7688
  }
7683
7689
  } catch (err) {
@@ -15267,7 +15273,10 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
15267
15273
  if (memoryId) cacheRowVector(cache, memoryId, Float32Array.from(embedding), updatedAt, content);
15268
15274
  if (vaultCtx && memoryId) {
15269
15275
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
15270
- updateVaultMemoryEmbeddingOp(vaultCtx, memoryId, JSON.stringify(embedding), currentModel).catch(
15276
+ updateVaultMemoryEmbeddingOp(vaultCtx, memoryId, JSON.stringify(embedding), currentModel, {
15277
+ content,
15278
+ ...updatedAt !== void 0 && { updatedAt: updatedAt.getTime() }
15279
+ }).catch(
15271
15280
  // Silently swallow – SDK must not use console.*; embedding will be retried on next search
15272
15281
  () => {
15273
15282
  }
@@ -18788,6 +18797,349 @@ function parseAnswer(body, base, parseSchema) {
18788
18797
  };
18789
18798
  }
18790
18799
 
18800
+ // src/lib/memory/store/local.ts
18801
+ import { Q as Q8 } from "@nozbe/watermelondb";
18802
+
18803
+ // src/lib/memory/topicExtract.ts
18804
+ var TOPIC_EXTRACTION_BATCH_SIZE = 10;
18805
+ var MAX_CHARS_PER_MEMORY = 300;
18806
+ var MAX_VOCABULARY_NAMES = 100;
18807
+ var MAX_COMPLETION_TOKENS = 8192;
18808
+ var SYSTEM_PROMPT5 = `You assign topics to saved memories for a personal memory system.
18809
+
18810
+ Each memory is a short statement about the user. For each memory, list the NAMED entities it mentions \u2014 these become the memory's topics, used to connect related memories in a knowledge graph.
18811
+
18812
+ Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
18813
+ - SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
18814
+ - KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
18815
+ - Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
18816
+ ${ENTITY_KIND_GUIDELINES}
18817
+
18818
+ Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
18819
+ - exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
18820
+ - "entities" may be empty when a memory mentions no named entities \u2014 most short memories have 0-3
18821
+ No prose.`;
18822
+ async function extractEntitiesForMemories(memories, options) {
18823
+ const out = /* @__PURE__ */ new Map();
18824
+ if (memories.length === 0) return out;
18825
+ const redactor = resolvePiiRedactor(options.piiRedaction);
18826
+ const vocabulary = [];
18827
+ for (const name of (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES)) {
18828
+ vocabulary.push(redactor ? (await redactor.redactTextAsync(name)).text : name);
18829
+ }
18830
+ const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
18831
+ When a memory refers to one of these, reuse the EXACT existing name (same spelling, casing, spacing and punctuation) instead of a variant \u2014 if "Foo.ai" is listed, never emit "Foo ai" or "Foo AI", and if "Jane Roe" is listed, emit that rather than a bare "Jane".
18832
+
18833
+ ` : "";
18834
+ for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
18835
+ const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
18836
+ const rows = [];
18837
+ for (const m of batch) {
18838
+ const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
18839
+ rows.push(`${m.id}: ${redactor ? (await redactor.redactTextAsync(content)).text : content}`);
18840
+ }
18841
+ const listing = rows.join("\n");
18842
+ const parsed = await callPortalJsonCompletion({
18843
+ ...options.apiKey !== void 0 && { apiKey: options.apiKey },
18844
+ ...options.getToken !== void 0 && { getToken: options.getToken },
18845
+ ...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
18846
+ taskType: "memory_topic",
18847
+ ...options.endpointOverride !== void 0 && {
18848
+ endpointOverride: options.endpointOverride
18849
+ },
18850
+ model: options.model ?? DEFAULT_EXTRACTION_MODEL,
18851
+ systemPrompt: SYSTEM_PROMPT5,
18852
+ userMessage: `${vocabularyNote}Memories:
18853
+ ${listing}
18854
+
18855
+ List each memory's named entities.`,
18856
+ tag: "memory/topics",
18857
+ extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
18858
+ ...options.fetchFn && { fetchFn: options.fetchFn },
18859
+ ...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
18860
+ ...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
18861
+ ...options.totalTimeoutMs !== void 0 && { totalTimeoutMs: options.totalTimeoutMs },
18862
+ ...options.backoffMs && { backoffMs: options.backoffMs }
18863
+ });
18864
+ if (parsed === null) {
18865
+ getLogger().warn(
18866
+ `[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
18867
+ );
18868
+ continue;
18869
+ }
18870
+ const validIds = new Set(batch.map((m) => m.id));
18871
+ const byId = parseTopicResponse(parsed, validIds);
18872
+ if (byId === null) {
18873
+ getLogger().warn(
18874
+ `[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
18875
+ );
18876
+ continue;
18877
+ }
18878
+ for (const m of batch) {
18879
+ const entities = byId.get(m.id);
18880
+ if (entities === void 0) {
18881
+ continue;
18882
+ }
18883
+ out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
18884
+ }
18885
+ }
18886
+ return out;
18887
+ }
18888
+ function restoreEntities(entities, redactor) {
18889
+ return entities.map((e) => ({ kind: e.kind, restored: redactor.restoreForStorage(e.name) })).filter((e) => !e.restored.unresolved).map(
18890
+ (e) => e.kind !== void 0 ? { name: e.restored.text, kind: e.kind } : { name: e.restored.text }
18891
+ );
18892
+ }
18893
+ function parseTopicResponse(parsed, validIds) {
18894
+ if (typeof parsed !== "object" || parsed === null) return null;
18895
+ const list = parsed.memories;
18896
+ if (!Array.isArray(list)) return null;
18897
+ const out = /* @__PURE__ */ new Map();
18898
+ for (const raw of list) {
18899
+ if (typeof raw !== "object" || raw === null) continue;
18900
+ const obj = raw;
18901
+ if (typeof obj.id !== "string") continue;
18902
+ const id = obj.id.trim().replace(/:$/, "").replace(/^\[([\s\S]*)\]$/, "$1").trim();
18903
+ if (!validIds.has(id) || out.has(id)) continue;
18904
+ const entities = Array.isArray(obj.entities) ? parseEntities(obj.entities) : [];
18905
+ out.set(id, entities);
18906
+ }
18907
+ return out;
18908
+ }
18909
+ var DEGRADED_TOPIC_SKIP = {
18910
+ excluded: false,
18911
+ "link-declined": false,
18912
+ "stamp-declined": false,
18913
+ "llm-unanswered": true,
18914
+ unreadable: true,
18915
+ "not-found": true,
18916
+ "link-failed": true
18917
+ };
18918
+ function isDegradedTopicSkip(reason) {
18919
+ return DEGRADED_TOPIC_SKIP[reason] === true;
18920
+ }
18921
+ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
18922
+ const entityCtx = ctx.entityCtx;
18923
+ if (!entityCtx) {
18924
+ throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
18925
+ }
18926
+ const log = getLogger();
18927
+ const extractedAt = options.now ?? Date.now();
18928
+ const skippedIds = [];
18929
+ const skippedReasons = /* @__PURE__ */ new Map();
18930
+ const skip = (id, reason) => {
18931
+ if (skippedReasons.has(id)) return;
18932
+ skippedIds.push(id);
18933
+ skippedReasons.set(id, reason);
18934
+ };
18935
+ const inputs = [];
18936
+ for (const id of new Set(memoryIds)) {
18937
+ let record;
18938
+ try {
18939
+ record = await ctx.vaultMemoryCollection.find(id);
18940
+ } catch (err) {
18941
+ log.warn("[memory/topics] vault lookup failed for extraction", err);
18942
+ skip(id, "not-found");
18943
+ continue;
18944
+ }
18945
+ if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
18946
+ skip(id, "excluded");
18947
+ continue;
18948
+ }
18949
+ try {
18950
+ const stored = await vaultMemoryToStored(
18951
+ record,
18952
+ ctx.walletAddress,
18953
+ ctx.signMessage,
18954
+ ctx.embeddedWalletSigner
18955
+ );
18956
+ inputs.push({ id, content: stored.content });
18957
+ } catch (err) {
18958
+ log.warn("[memory/topics] failed to load memory for extraction", err);
18959
+ skip(id, "unreadable");
18960
+ }
18961
+ }
18962
+ const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
18963
+ const toStamp = [];
18964
+ for (const input of inputs) {
18965
+ const entities = entitiesByMemory.get(input.id);
18966
+ if (entities === void 0) {
18967
+ skip(input.id, "llm-unanswered");
18968
+ continue;
18969
+ }
18970
+ try {
18971
+ const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
18972
+ if (linked === null) {
18973
+ skip(input.id, "link-declined");
18974
+ entitiesByMemory.delete(input.id);
18975
+ continue;
18976
+ }
18977
+ } catch (err) {
18978
+ log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
18979
+ skip(input.id, "link-failed");
18980
+ entitiesByMemory.delete(input.id);
18981
+ continue;
18982
+ }
18983
+ toStamp.push(input.id);
18984
+ }
18985
+ const stampedIds = await stampTopicsExtractedAtOp(ctx, toStamp, extractedAt);
18986
+ const stampedSet = new Set(stampedIds);
18987
+ for (const id of toStamp) {
18988
+ if (!stampedSet.has(id)) {
18989
+ skip(id, "stamp-declined");
18990
+ entitiesByMemory.delete(id);
18991
+ }
18992
+ }
18993
+ return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
18994
+ }
18995
+
18996
+ // src/lib/memory/store/local.ts
18997
+ function createLocalMemoryStore(options) {
18998
+ const { database, userId } = options;
18999
+ const entityCtx = {
19000
+ database,
19001
+ entityCollection: database.get("entity"),
19002
+ memoryEntityCollection: database.get("memory_entity"),
19003
+ ...userId !== void 0 && { userId },
19004
+ ...options.allowUnscopedRows !== void 0 && {
19005
+ allowUnscopedRows: options.allowUnscopedRows
19006
+ }
19007
+ };
19008
+ const vaultCtx = {
19009
+ database,
19010
+ vaultMemoryCollection: database.get("memory_vault"),
19011
+ walletAddress: options.walletAddress,
19012
+ signMessage: options.signMessage,
19013
+ embeddedWalletSigner: options.embeddedWalletSigner,
19014
+ ...userId !== void 0 && { userId },
19015
+ ...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
19016
+ // Deletes cascade to memory_entity, so the graph lane never serves a
19017
+ // deleted memory's id.
19018
+ entityCtx
19019
+ };
19020
+ const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
19021
+ const ownedBy = userId !== void 0 ? [Q8.where("user_id", userId)] : [];
19022
+ const watchedColumns = [
19023
+ "content",
19024
+ "scope",
19025
+ "updated_at",
19026
+ "fact_type",
19027
+ "event_time_start",
19028
+ "event_time_end",
19029
+ "event_time_kind",
19030
+ "archived_at",
19031
+ "trust_tier",
19032
+ "superseded_by",
19033
+ "visibility",
19034
+ "published_at",
19035
+ "geohash",
19036
+ "topics",
19037
+ "topics_user_managed",
19038
+ "media",
19039
+ "source"
19040
+ ];
19041
+ const embedInBackground = (memory) => {
19042
+ eagerEmbedContent(
19043
+ memory.content,
19044
+ options.embeddingOptions,
19045
+ vaultCache,
19046
+ vaultCtx,
19047
+ memory.uniqueId,
19048
+ memory.updatedAt
19049
+ ).catch((err) => {
19050
+ getLogger().warn("[memory/store] Failed to embed memory:", err);
19051
+ });
19052
+ };
19053
+ return {
19054
+ list: (listOptions) => getAllVaultMemoriesOp(vaultCtx, listOptions),
19055
+ get: (id) => getVaultMemoryOp(vaultCtx, id),
19056
+ listArchived: async () => {
19057
+ const ids = await vaultCtx.vaultMemoryCollection.query(Q8.where("is_deleted", false), Q8.where("archived_at", Q8.notEq(null)), ...ownedBy).fetchIds();
19058
+ if (ids.length === 0) return [];
19059
+ const rows = await getAllVaultMemoriesOp(vaultCtx, { memoryIds: ids, includeArchived: true });
19060
+ return rows.sort((a, b) => (b.archivedAt ?? 0) - (a.archivedAt ?? 0));
19061
+ },
19062
+ memoriesByTopics: (names) => getMemoriesByEntityNamesOp(entityCtx, names),
19063
+ topicsByMemories: (memoryIds) => getEntitiesByMemoryIdsOp(entityCtx, memoryIds),
19064
+ create: async (input) => {
19065
+ const created = await createVaultMemoryOp(vaultCtx, input);
19066
+ if (input.embedding === void 0) embedInBackground(created);
19067
+ return created;
19068
+ },
19069
+ createMany: async (inputs) => {
19070
+ const created = await createVaultMemoriesBatchOp(vaultCtx, inputs);
19071
+ created.forEach((memory, i) => {
19072
+ if (inputs[i].embedding === void 0) embedInBackground(memory);
19073
+ });
19074
+ return created;
19075
+ },
19076
+ update: async (id, patch) => {
19077
+ const reembed = patch.embedding === void 0;
19078
+ const updated = await updateVaultMemoryOp(
19079
+ vaultCtx,
19080
+ id,
19081
+ reembed ? { ...patch, embedding: null } : patch
19082
+ );
19083
+ if (!updated) return null;
19084
+ vaultCache.delete(id);
19085
+ if (reembed) embedInBackground(updated);
19086
+ return updated;
19087
+ },
19088
+ delete: async (id) => {
19089
+ const deleted = await deleteVaultMemoryOp(vaultCtx, id);
19090
+ if (deleted) vaultCache.delete(id);
19091
+ return deleted;
19092
+ },
19093
+ supersede: (id, supersededById) => supersedeVaultMemoryOp(vaultCtx, id, supersededById),
19094
+ archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
19095
+ restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
19096
+ setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
19097
+ addTopics: (memoryId, topics) => database.write(async (writer) => {
19098
+ const owned = await vaultCtx.vaultMemoryCollection.query(Q8.where("id", memoryId), Q8.where("is_deleted", false), ...ownedBy).fetchCount();
19099
+ return owned > 0 ? writer.callWriter(() => linkMemoryEntitiesOp(entityCtx, memoryId, topics)) : [];
19100
+ }),
19101
+ setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
19102
+ recall: (query, recallOptions) => recall(
19103
+ query,
19104
+ { vaultCtx, entityCtx, embeddingOptions: options.embeddingOptions, vaultCache },
19105
+ { ...recallOptions, types: ["fact"] }
19106
+ ),
19107
+ retain: (content, retainOptions) => retain(
19108
+ content,
19109
+ { vaultCtx, embeddingOptions: options.embeddingOptions, vaultCache },
19110
+ retainOptions
19111
+ ),
19112
+ subscribe: (onChange, subscribeOptions) => {
19113
+ const afterFirst = () => {
19114
+ let first = true;
19115
+ return () => {
19116
+ if (first) first = false;
19117
+ else onChange();
19118
+ };
19119
+ };
19120
+ const memories = subscribeOptions?.includeDeleted ? vaultCtx.vaultMemoryCollection.query(...ownedBy).observe() : vaultCtx.vaultMemoryCollection.query(Q8.where("is_deleted", false), ...ownedBy).observeWithColumns(
19121
+ subscribeOptions?.embeddings ? [...watchedColumns, "embedding", "embedding_model"] : watchedColumns
19122
+ );
19123
+ const subscriptions = [memories.subscribe(afterFirst())];
19124
+ if (subscribeOptions?.topics) {
19125
+ const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [Q8.or(Q8.where("user_id", userId), Q8.where("user_id", null))] : [Q8.where("user_id", userId)];
19126
+ subscriptions.push(
19127
+ entityCtx.memoryEntityCollection.query(...linksOwnedBy).observe().subscribe(afterFirst())
19128
+ );
19129
+ }
19130
+ return () => subscriptions.forEach((s) => s.unsubscribe());
19131
+ },
19132
+ maintenance: {
19133
+ createDecaySweeper: (sweeperOptions) => createDecaySweeper({ ...sweeperOptions, vaultCtx }),
19134
+ getTopicBacklog: (backlogOptions) => getMemoriesNeedingTopicExtractionOp(vaultCtx, backlogOptions),
19135
+ extractTopics: (memoryIds, extractOptions) => extractAndLinkEntitiesForMemoriesOp(vaultCtx, memoryIds, extractOptions),
19136
+ stampTopicsExtracted: (memoryIds, extractedAt, version) => stampTopicsExtractedAtOp(vaultCtx, memoryIds, extractedAt, version),
19137
+ relinkTopics: (memoryIds) => relinkMemoryTopicsOp(vaultCtx, memoryIds),
19138
+ backfillTopics: (memoryIds) => backfillMemoryTopicsOp(vaultCtx, memoryIds)
19139
+ }
19140
+ };
19141
+ }
19142
+
18791
19143
  // src/lib/memory/synthesizeProfile.ts
18792
19144
  var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
18793
19145
  var DEFAULT_FACET_RECALL_LIMIT = 20;
@@ -19315,199 +19667,6 @@ function normalizeInterests(values) {
19315
19667
  return out.length > 0 ? out : void 0;
19316
19668
  }
19317
19669
 
19318
- // src/lib/memory/topicExtract.ts
19319
- var TOPIC_EXTRACTION_BATCH_SIZE = 10;
19320
- var MAX_CHARS_PER_MEMORY = 300;
19321
- var MAX_VOCABULARY_NAMES = 100;
19322
- var MAX_COMPLETION_TOKENS = 8192;
19323
- var SYSTEM_PROMPT5 = `You assign topics to saved memories for a personal memory system.
19324
-
19325
- Each memory is a short statement about the user. For each memory, list the NAMED entities it mentions \u2014 these become the memory's topics, used to connect related memories in a knowledge graph.
19326
-
19327
- Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
19328
- - SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
19329
- - KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
19330
- - Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
19331
- ${ENTITY_KIND_GUIDELINES}
19332
-
19333
- Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
19334
- - exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
19335
- - "entities" may be empty when a memory mentions no named entities \u2014 most short memories have 0-3
19336
- No prose.`;
19337
- async function extractEntitiesForMemories(memories, options) {
19338
- const out = /* @__PURE__ */ new Map();
19339
- if (memories.length === 0) return out;
19340
- const redactor = resolvePiiRedactor(options.piiRedaction);
19341
- const vocabulary = [];
19342
- for (const name of (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES)) {
19343
- vocabulary.push(redactor ? (await redactor.redactTextAsync(name)).text : name);
19344
- }
19345
- const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
19346
- When a memory refers to one of these, reuse the EXACT existing name (same spelling, casing, spacing and punctuation) instead of a variant \u2014 if "Foo.ai" is listed, never emit "Foo ai" or "Foo AI", and if "Jane Roe" is listed, emit that rather than a bare "Jane".
19347
-
19348
- ` : "";
19349
- for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
19350
- const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
19351
- const rows = [];
19352
- for (const m of batch) {
19353
- const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
19354
- rows.push(`${m.id}: ${redactor ? (await redactor.redactTextAsync(content)).text : content}`);
19355
- }
19356
- const listing = rows.join("\n");
19357
- const parsed = await callPortalJsonCompletion({
19358
- ...options.apiKey !== void 0 && { apiKey: options.apiKey },
19359
- ...options.getToken !== void 0 && { getToken: options.getToken },
19360
- ...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
19361
- taskType: "memory_topic",
19362
- ...options.endpointOverride !== void 0 && {
19363
- endpointOverride: options.endpointOverride
19364
- },
19365
- model: options.model ?? DEFAULT_EXTRACTION_MODEL,
19366
- systemPrompt: SYSTEM_PROMPT5,
19367
- userMessage: `${vocabularyNote}Memories:
19368
- ${listing}
19369
-
19370
- List each memory's named entities.`,
19371
- tag: "memory/topics",
19372
- extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
19373
- ...options.fetchFn && { fetchFn: options.fetchFn },
19374
- ...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
19375
- ...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
19376
- ...options.totalTimeoutMs !== void 0 && { totalTimeoutMs: options.totalTimeoutMs },
19377
- ...options.backoffMs && { backoffMs: options.backoffMs }
19378
- });
19379
- if (parsed === null) {
19380
- getLogger().warn(
19381
- `[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
19382
- );
19383
- continue;
19384
- }
19385
- const validIds = new Set(batch.map((m) => m.id));
19386
- const byId = parseTopicResponse(parsed, validIds);
19387
- if (byId === null) {
19388
- getLogger().warn(
19389
- `[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
19390
- );
19391
- continue;
19392
- }
19393
- for (const m of batch) {
19394
- const entities = byId.get(m.id);
19395
- if (entities === void 0) {
19396
- continue;
19397
- }
19398
- out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
19399
- }
19400
- }
19401
- return out;
19402
- }
19403
- function restoreEntities(entities, redactor) {
19404
- return entities.map((e) => ({ kind: e.kind, restored: redactor.restoreForStorage(e.name) })).filter((e) => !e.restored.unresolved).map(
19405
- (e) => e.kind !== void 0 ? { name: e.restored.text, kind: e.kind } : { name: e.restored.text }
19406
- );
19407
- }
19408
- function parseTopicResponse(parsed, validIds) {
19409
- if (typeof parsed !== "object" || parsed === null) return null;
19410
- const list = parsed.memories;
19411
- if (!Array.isArray(list)) return null;
19412
- const out = /* @__PURE__ */ new Map();
19413
- for (const raw of list) {
19414
- if (typeof raw !== "object" || raw === null) continue;
19415
- const obj = raw;
19416
- if (typeof obj.id !== "string") continue;
19417
- const id = obj.id.trim().replace(/:$/, "").replace(/^\[([\s\S]*)\]$/, "$1").trim();
19418
- if (!validIds.has(id) || out.has(id)) continue;
19419
- const entities = Array.isArray(obj.entities) ? parseEntities(obj.entities) : [];
19420
- out.set(id, entities);
19421
- }
19422
- return out;
19423
- }
19424
- var DEGRADED_TOPIC_SKIP = {
19425
- excluded: false,
19426
- "link-declined": false,
19427
- "stamp-declined": false,
19428
- "llm-unanswered": true,
19429
- unreadable: true,
19430
- "not-found": true,
19431
- "link-failed": true
19432
- };
19433
- function isDegradedTopicSkip(reason) {
19434
- return DEGRADED_TOPIC_SKIP[reason] === true;
19435
- }
19436
- async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
19437
- const entityCtx = ctx.entityCtx;
19438
- if (!entityCtx) {
19439
- throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
19440
- }
19441
- const log = getLogger();
19442
- const extractedAt = options.now ?? Date.now();
19443
- const skippedIds = [];
19444
- const skippedReasons = /* @__PURE__ */ new Map();
19445
- const skip = (id, reason) => {
19446
- if (skippedReasons.has(id)) return;
19447
- skippedIds.push(id);
19448
- skippedReasons.set(id, reason);
19449
- };
19450
- const inputs = [];
19451
- for (const id of new Set(memoryIds)) {
19452
- let record;
19453
- try {
19454
- record = await ctx.vaultMemoryCollection.find(id);
19455
- } catch (err) {
19456
- log.warn("[memory/topics] vault lookup failed for extraction", err);
19457
- skip(id, "not-found");
19458
- continue;
19459
- }
19460
- if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
19461
- skip(id, "excluded");
19462
- continue;
19463
- }
19464
- try {
19465
- const stored = await vaultMemoryToStored(
19466
- record,
19467
- ctx.walletAddress,
19468
- ctx.signMessage,
19469
- ctx.embeddedWalletSigner
19470
- );
19471
- inputs.push({ id, content: stored.content });
19472
- } catch (err) {
19473
- log.warn("[memory/topics] failed to load memory for extraction", err);
19474
- skip(id, "unreadable");
19475
- }
19476
- }
19477
- const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
19478
- const toStamp = [];
19479
- for (const input of inputs) {
19480
- const entities = entitiesByMemory.get(input.id);
19481
- if (entities === void 0) {
19482
- skip(input.id, "llm-unanswered");
19483
- continue;
19484
- }
19485
- try {
19486
- const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
19487
- if (linked === null) {
19488
- skip(input.id, "link-declined");
19489
- entitiesByMemory.delete(input.id);
19490
- continue;
19491
- }
19492
- } catch (err) {
19493
- log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
19494
- skip(input.id, "link-failed");
19495
- entitiesByMemory.delete(input.id);
19496
- continue;
19497
- }
19498
- toStamp.push(input.id);
19499
- }
19500
- const stampedIds = await stampTopicsExtractedAtOp(ctx, toStamp, extractedAt);
19501
- const stampedSet = new Set(stampedIds);
19502
- for (const id of toStamp) {
19503
- if (!stampedSet.has(id)) {
19504
- skip(id, "stamp-declined");
19505
- entitiesByMemory.delete(id);
19506
- }
19507
- }
19508
- return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
19509
- }
19510
-
19511
19670
  // src/lib/memory/verifySupport.ts
19512
19671
  var DEFAULT_MODEL5 = "inclusionai/ling-2.6-flash";
19513
19672
  var DEFAULT_ATTEMPTS3 = 2;
@@ -19898,7 +20057,7 @@ async function assembleMemoryContext(options) {
19898
20057
  }
19899
20058
 
19900
20059
  // src/lib/memory/durableExtraction.ts
19901
- import { Q as Q8 } from "@nozbe/watermelondb";
20060
+ import { Q as Q9 } from "@nozbe/watermelondb";
19902
20061
  var MAX_JOBS_PER_PASS = 3;
19903
20062
  var MAX_ATTEMPTS = 3;
19904
20063
  var MAX_FAILED_SESSIONS = 3;
@@ -20045,7 +20204,7 @@ function createDurableAutoExtractor(options) {
20045
20204
  ...options.retainCtx,
20046
20205
  vaultCtx: {
20047
20206
  ...vault,
20048
- canWrite: async () => !disposed && !cancelled && await storage.conversationsCollection.query(Q8.where("conversation_id", conversationId), Q8.where("is_deleted", false)).fetchCount() > 0 && await storage.messagesCollection.query(Q8.where("conversation_id", conversationId), Q8.where("id", Q8.oneOf(ids))).fetchCount() === ids.length && (!vault.canWrite || await vault.canWrite()) && !disposed && !cancelled
20207
+ canWrite: async () => !disposed && !cancelled && await storage.conversationsCollection.query(Q9.where("conversation_id", conversationId), Q9.where("is_deleted", false)).fetchCount() > 0 && await storage.messagesCollection.query(Q9.where("conversation_id", conversationId), Q9.where("id", Q9.oneOf(ids))).fetchCount() === ids.length && (!vault.canWrite || await vault.canWrite()) && !disposed && !cancelled
20049
20208
  }
20050
20209
  },
20051
20210
  // The model follows the job's scope, not the mode alive at drain time.
@@ -20187,7 +20346,7 @@ function createDurableAutoExtractor(options) {
20187
20346
  let scheduleAfterSuccess = false;
20188
20347
  try {
20189
20348
  await writes;
20190
- const pending = await jobs.query(Q8.where("owner_key", owner), Q8.where("message_ids", Q8.notEq("[]"))).fetch();
20349
+ const pending = await jobs.query(Q9.where("owner_key", owner), Q9.where("message_ids", Q9.notEq("[]"))).fetch();
20191
20350
  storeFailures = 0;
20192
20351
  let processed = 0;
20193
20352
  for (const job of pending) {
@@ -20203,7 +20362,7 @@ function createDurableAutoExtractor(options) {
20203
20362
  let ids = [];
20204
20363
  let loaded = [];
20205
20364
  try {
20206
- const conversations = await storage.conversationsCollection.query(Q8.where("conversation_id", conversationId), Q8.where("is_deleted", false)).fetchCount();
20365
+ const conversations = await storage.conversationsCollection.query(Q9.where("conversation_id", conversationId), Q9.where("is_deleted", false)).fetchCount();
20207
20366
  if (!conversations) {
20208
20367
  await database.write(() => job.destroyPermanently());
20209
20368
  continue;
@@ -20320,12 +20479,12 @@ function createDurableAutoExtractor(options) {
20320
20479
  const scope = currentScope();
20321
20480
  writes = writes.then(
20322
20481
  () => database.write(async () => {
20323
- const existing = await jobs.query(Q8.where("owner_key", owner), Q8.where("conversation_id", conversationId)).fetch();
20482
+ const existing = await jobs.query(Q9.where("owner_key", owner), Q9.where("conversation_id", conversationId)).fetch();
20324
20483
  const job = existing.find(
20325
20484
  (candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
20326
20485
  );
20327
20486
  const positions = new Map(ids.map((id, index) => [id, index]));
20328
- const rows = await storage.messagesCollection.query(Q8.where("id", Q8.oneOf(ids))).fetch();
20487
+ const rows = await storage.messagesCollection.query(Q9.where("id", Q9.oneOf(ids))).fetch();
20329
20488
  const sequences = /* @__PURE__ */ new Map();
20330
20489
  for (const row of rows) {
20331
20490
  const sequence = Number(row._getRaw("message_id"));
@@ -25980,7 +26139,7 @@ function useDatabaseManager(walletAddress, manager) {
25980
26139
  }
25981
26140
 
25982
26141
  // src/lib/db/project/operations.ts
25983
- import { Q as Q9 } from "@nozbe/watermelondb";
26142
+ import { Q as Q10 } from "@nozbe/watermelondb";
25984
26143
 
25985
26144
  // src/lib/db/project/types.ts
25986
26145
  function generateProjectId() {
@@ -26011,15 +26170,15 @@ async function createProjectOp(ctx, opts, defaultName = "New Project") {
26011
26170
  return projectToStored(created);
26012
26171
  }
26013
26172
  async function getProjectOp(ctx, id) {
26014
- const results = await ctx.projectsCollection.query(Q9.where("project_id", id), Q9.where("is_deleted", false)).fetch();
26173
+ const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
26015
26174
  return results.length > 0 ? projectToStored(results[0]) : null;
26016
26175
  }
26017
26176
  async function getProjectsOp(ctx) {
26018
- const results = await ctx.projectsCollection.query(Q9.where("is_deleted", false), Q9.sortBy("created_at", Q9.desc)).fetch();
26177
+ const results = await ctx.projectsCollection.query(Q10.where("is_deleted", false), Q10.sortBy("created_at", Q10.desc)).fetch();
26019
26178
  return results.map(projectToStored);
26020
26179
  }
26021
26180
  async function updateProjectNameOp(ctx, id, name) {
26022
- const results = await ctx.projectsCollection.query(Q9.where("project_id", id), Q9.where("is_deleted", false)).fetch();
26181
+ const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
26023
26182
  if (results.length > 0) {
26024
26183
  await ctx.database.write(async () => {
26025
26184
  await results[0].update((proj) => {
@@ -26031,7 +26190,7 @@ async function updateProjectNameOp(ctx, id, name) {
26031
26190
  return false;
26032
26191
  }
26033
26192
  async function updateProjectOp(ctx, id, opts) {
26034
- const results = await ctx.projectsCollection.query(Q9.where("project_id", id), Q9.where("is_deleted", false)).fetch();
26193
+ const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
26035
26194
  if (results.length > 0) {
26036
26195
  await ctx.database.write(async () => {
26037
26196
  await results[0].update((proj) => {
@@ -26043,7 +26202,7 @@ async function updateProjectOp(ctx, id, opts) {
26043
26202
  return false;
26044
26203
  }
26045
26204
  async function deleteProjectOp(ctx, id) {
26046
- const results = await ctx.projectsCollection.query(Q9.where("project_id", id), Q9.where("is_deleted", false)).fetch();
26205
+ const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
26047
26206
  if (results.length > 0) {
26048
26207
  await ctx.database.write(async () => {
26049
26208
  await results[0].update((proj) => {
@@ -26056,18 +26215,18 @@ async function deleteProjectOp(ctx, id) {
26056
26215
  }
26057
26216
  async function getProjectConversationsOp(ctx, projectId) {
26058
26217
  const results = await ctx.conversationsCollection.query(
26059
- Q9.where("project_id", projectId),
26060
- Q9.where("is_deleted", false),
26061
- Q9.sortBy("created_at", Q9.desc)
26218
+ Q10.where("project_id", projectId),
26219
+ Q10.where("is_deleted", false),
26220
+ Q10.sortBy("created_at", Q10.desc)
26062
26221
  ).fetch();
26063
26222
  return results.map(conversationToStoredRaw);
26064
26223
  }
26065
26224
  async function getProjectConversationCountOp(ctx, projectId) {
26066
- return await ctx.conversationsCollection.query(Q9.where("project_id", projectId), Q9.where("is_deleted", false)).fetchCount();
26225
+ return await ctx.conversationsCollection.query(Q10.where("project_id", projectId), Q10.where("is_deleted", false)).fetchCount();
26067
26226
  }
26068
26227
 
26069
26228
  // src/react/useFiles.ts
26070
- import { Q as Q10 } from "@nozbe/watermelondb";
26229
+ import { Q as Q11 } from "@nozbe/watermelondb";
26071
26230
  import { useCallback as useCallback5, useEffect as useEffect4, useMemo as useMemo5, useState as useState5 } from "react";
26072
26231
  function useFiles(options) {
26073
26232
  const { database, walletAddress } = options;
@@ -26085,7 +26244,7 @@ function useFiles(options) {
26085
26244
  setIsLoading(true);
26086
26245
  try {
26087
26246
  const coll = database.get("media");
26088
- await coll.query(Q10.take(1)).fetch();
26247
+ await coll.query(Q11.take(1)).fetch();
26089
26248
  setMediaCollection(coll);
26090
26249
  setIsReady(true);
26091
26250
  } catch (error) {
@@ -26493,7 +26652,7 @@ function useFiles(options) {
26493
26652
  }
26494
26653
 
26495
26654
  // src/react/useProjects.ts
26496
- import { Q as Q11 } from "@nozbe/watermelondb";
26655
+ import { Q as Q12 } from "@nozbe/watermelondb";
26497
26656
  import { useCallback as useCallback6, useEffect as useEffect5, useMemo as useMemo6, useState as useState6 } from "react";
26498
26657
  function useProjects(options) {
26499
26658
  const { database, initialProjectId } = options;
@@ -26515,7 +26674,7 @@ function useProjects(options) {
26515
26674
  conversations: convColl?.table
26516
26675
  });
26517
26676
  getLogger().debug("[useProjects] Running test query on projects table...");
26518
- const testResult = await projColl.query(Q11.take(1)).fetch();
26677
+ const testResult = await projColl.query(Q12.take(1)).fetch();
26519
26678
  getLogger().debug(
26520
26679
  "[useProjects] Test query succeeded, found",
26521
26680
  testResult.length,
@@ -26602,7 +26761,7 @@ function useProjects(options) {
26602
26761
  if (!projectsCollection) {
26603
26762
  return;
26604
26763
  }
26605
- const subscription = projectsCollection.query(Q11.where("is_deleted", false)).observe().subscribe((records) => {
26764
+ const subscription = projectsCollection.query(Q12.where("is_deleted", false)).observe().subscribe((records) => {
26606
26765
  setProjects(records.map(projectToStored));
26607
26766
  });
26608
26767
  return () => subscription.unsubscribe();
@@ -26725,7 +26884,7 @@ function useProjects(options) {
26725
26884
  }
26726
26885
 
26727
26886
  // src/lib/db/settings/operations.ts
26728
- import { Q as Q12 } from "@nozbe/watermelondb";
26887
+ import { Q as Q13 } from "@nozbe/watermelondb";
26729
26888
  function modelPreferenceToStored(preference) {
26730
26889
  return {
26731
26890
  uniqueId: preference.id,
@@ -26734,12 +26893,12 @@ function modelPreferenceToStored(preference) {
26734
26893
  };
26735
26894
  }
26736
26895
  async function getModelPreferenceOp(ctx, walletAddress) {
26737
- const results = await ctx.modelPreferencesCollection.query(Q12.where("wallet_address", walletAddress)).fetch();
26896
+ const results = await ctx.modelPreferencesCollection.query(Q13.where("wallet_address", walletAddress)).fetch();
26738
26897
  return results.length > 0 ? modelPreferenceToStored(results[0]) : null;
26739
26898
  }
26740
26899
  async function setModelPreferenceOp(ctx, walletAddress, models) {
26741
26900
  const result = await ctx.database.write(async () => {
26742
- const results = await ctx.modelPreferencesCollection.query(Q12.where("wallet_address", walletAddress)).fetch();
26901
+ const results = await ctx.modelPreferencesCollection.query(Q13.where("wallet_address", walletAddress)).fetch();
26743
26902
  if (results.length > 0) {
26744
26903
  const preference = results[0];
26745
26904
  await preference.update((pref) => {
@@ -26757,7 +26916,7 @@ async function setModelPreferenceOp(ctx, walletAddress, models) {
26757
26916
  return modelPreferenceToStored(result);
26758
26917
  }
26759
26918
  async function deleteModelPreferenceOp(ctx, walletAddress) {
26760
- const results = await ctx.modelPreferencesCollection.query(Q12.where("wallet_address", walletAddress)).fetch();
26919
+ const results = await ctx.modelPreferencesCollection.query(Q13.where("wallet_address", walletAddress)).fetch();
26761
26920
  if (results.length === 0) return false;
26762
26921
  await ctx.database.write(async () => {
26763
26922
  await results[0].destroyPermanently();
@@ -26781,7 +26940,7 @@ var settingsStorageSchema = appSchema3({
26781
26940
  });
26782
26941
 
26783
26942
  // src/lib/db/vaultFolders/operations.ts
26784
- import { Q as Q13 } from "@nozbe/watermelondb";
26943
+ import { Q as Q14 } from "@nozbe/watermelondb";
26785
26944
  function folderToStored(folder) {
26786
26945
  return {
26787
26946
  uniqueId: folder.id,
@@ -26806,7 +26965,7 @@ async function createVaultFolderOp(ctx, opts) {
26806
26965
  return folderToStored(created);
26807
26966
  }
26808
26967
  async function getAllVaultFoldersOp(ctx) {
26809
- const results = await ctx.vaultFolderCollection.query(Q13.where("is_deleted", false), Q13.sortBy("created_at", Q13.desc)).fetch();
26968
+ const results = await ctx.vaultFolderCollection.query(Q14.where("is_deleted", false), Q14.sortBy("created_at", Q14.desc)).fetch();
26810
26969
  return results.map(folderToStored);
26811
26970
  }
26812
26971
  async function updateVaultFolderOp(ctx, id, opts) {
@@ -26815,7 +26974,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
26815
26974
  if (record.isDeleted) return null;
26816
26975
  const scopeChanged = opts.scope !== void 0 && opts.scope !== record.scope;
26817
26976
  const updated = await ctx.database.write(async () => {
26818
- const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q13.where("folder_id", id), Q13.where("is_deleted", false)).fetch() : [];
26977
+ const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q14.where("folder_id", id), Q14.where("is_deleted", false)).fetch() : [];
26819
26978
  const updates = [];
26820
26979
  updates.push(
26821
26980
  record.prepareUpdate((r) => {
@@ -26843,7 +27002,7 @@ async function deleteVaultFolderOp(ctx, id) {
26843
27002
  const record = await ctx.vaultFolderCollection.find(id);
26844
27003
  if (record.isDeleted) return false;
26845
27004
  await ctx.database.write(async () => {
26846
- const memories = await ctx.vaultMemoryCollection.query(Q13.where("folder_id", id), Q13.where("is_deleted", false)).fetch();
27005
+ const memories = await ctx.vaultMemoryCollection.query(Q14.where("folder_id", id), Q14.where("is_deleted", false)).fetch();
26847
27006
  const preparedMemories = memories.map(
26848
27007
  (memory) => memory.prepareUpdate((r) => {
26849
27008
  r._setRaw("folder_id", null);
@@ -26912,7 +27071,7 @@ async function updateVaultFolderContextOp(ctx, id, context) {
26912
27071
  }
26913
27072
  }
26914
27073
  async function getVaultFolderMemoryCountOp(ctx, folderId) {
26915
- return await ctx.vaultMemoryCollection.query(Q13.where("folder_id", folderId), Q13.where("is_deleted", false)).fetchCount();
27074
+ return await ctx.vaultMemoryCollection.query(Q14.where("folder_id", folderId), Q14.where("is_deleted", false)).fetchCount();
26916
27075
  }
26917
27076
 
26918
27077
  // src/lib/db/vaultFolders/defaults.ts
@@ -26958,7 +27117,7 @@ async function _ensureDefaultFoldersImpl(ctx) {
26958
27117
  import { useCallback as useCallback7, useMemo as useMemo7, useSyncExternalStore } from "react";
26959
27118
 
26960
27119
  // src/lib/db/userPreferences/operations.ts
26961
- import { Q as Q14 } from "@nozbe/watermelondb";
27120
+ import { Q as Q15 } from "@nozbe/watermelondb";
26962
27121
  function userPreferenceToStored(preference) {
26963
27122
  return {
26964
27123
  uniqueId: preference.id,
@@ -26973,7 +27132,7 @@ function userPreferenceToStored(preference) {
26973
27132
  };
26974
27133
  }
26975
27134
  async function getUserPreferenceOp(ctx, walletAddress) {
26976
- const results = await ctx.userPreferencesCollection.query(Q14.where("wallet_address", walletAddress)).fetch();
27135
+ const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
26977
27136
  return results.length > 0 ? userPreferenceToStored(results[0]) : null;
26978
27137
  }
26979
27138
  async function createUserPreferenceOp(ctx, opts) {
@@ -26993,7 +27152,7 @@ async function createUserPreferenceOp(ctx, opts) {
26993
27152
  return userPreferenceToStored(created);
26994
27153
  }
26995
27154
  async function updateUserPreferenceOp(ctx, walletAddress, opts) {
26996
- const results = await ctx.userPreferencesCollection.query(Q14.where("wallet_address", walletAddress)).fetch();
27155
+ const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
26997
27156
  if (results.length === 0) return null;
26998
27157
  const preference = results[0];
26999
27158
  await ctx.database.write(async () => {
@@ -27021,7 +27180,7 @@ async function updateUserPreferenceOp(ctx, walletAddress, opts) {
27021
27180
  async function setUserPreferenceOp(ctx, walletAddress, opts) {
27022
27181
  const now = Date.now();
27023
27182
  const result = await ctx.database.write(async () => {
27024
- const results = await ctx.userPreferencesCollection.query(Q14.where("wallet_address", walletAddress)).fetch();
27183
+ const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
27025
27184
  if (results.length > 0) {
27026
27185
  const preference = results[0];
27027
27186
  await preference.update((pref) => {
@@ -27069,7 +27228,7 @@ async function updateModelsOp(ctx, walletAddress, models) {
27069
27228
  return updateUserPreferenceOp(ctx, walletAddress, { models });
27070
27229
  }
27071
27230
  async function deleteUserPreferenceOp(ctx, walletAddress) {
27072
- const results = await ctx.userPreferencesCollection.query(Q14.where("wallet_address", walletAddress)).fetch();
27231
+ const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
27073
27232
  if (results.length === 0) return false;
27074
27233
  await ctx.database.write(async () => {
27075
27234
  await results[0].destroyPermanently();
@@ -27084,9 +27243,9 @@ async function migrateFromModelPreferencesOp(ctx, walletAddress) {
27084
27243
  if (existing) {
27085
27244
  return existing;
27086
27245
  }
27087
- const modelResults = await ctx.modelPreferencesCollection.query(Q14.where("wallet_address", walletAddress)).fetch();
27246
+ const modelResults = await ctx.modelPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
27088
27247
  const personalityKey = `${walletAddress}_personality_settings`;
27089
- const personalityResults = await ctx.modelPreferencesCollection.query(Q14.where("wallet_address", personalityKey)).fetch();
27248
+ const personalityResults = await ctx.modelPreferencesCollection.query(Q15.where("wallet_address", personalityKey)).fetch();
27090
27249
  if (modelResults.length === 0 && personalityResults.length === 0) {
27091
27250
  return null;
27092
27251
  }
@@ -27192,7 +27351,7 @@ var SLIDER_CONFIG = [
27192
27351
  ];
27193
27352
 
27194
27353
  // src/react/userSettingsStore.ts
27195
- import { Q as Q15 } from "@nozbe/watermelondb";
27354
+ import { Q as Q16 } from "@nozbe/watermelondb";
27196
27355
  var EMPTY_SNAPSHOT = Object.freeze({
27197
27356
  modelPreference: null,
27198
27357
  userPreference: null,
@@ -27254,7 +27413,7 @@ async function startLoad(entry, walletAddress) {
27254
27413
  }
27255
27414
  function startObserve(entry, walletAddress) {
27256
27415
  let isInitialEmission = true;
27257
- entry.observeSub = entry.storageCtx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).observeWithColumns([
27416
+ entry.observeSub = entry.storageCtx.userPreferencesCollection.query(Q16.where("wallet_address", walletAddress)).observeWithColumns([
27258
27417
  "nickname",
27259
27418
  "occupation",
27260
27419
  "description",
@@ -27518,7 +27677,7 @@ function useSettings(options) {
27518
27677
  }
27519
27678
 
27520
27679
  // src/lib/db/appFiles/operations.ts
27521
- import { Q as Q16 } from "@nozbe/watermelondb";
27680
+ import { Q as Q17 } from "@nozbe/watermelondb";
27522
27681
 
27523
27682
  // src/utils/paths.ts
27524
27683
  function normalizePath(p) {
@@ -27544,7 +27703,7 @@ async function putAppFileOp(ctx, conversationId, path, content) {
27544
27703
  const normalized = normalizePath(path);
27545
27704
  const now = Date.now();
27546
27705
  const result = await ctx.database.write(async () => {
27547
- const existing = await ctx.appFilesCollection.query(Q16.where("conversation_id", conversationId), Q16.where("path", normalized)).fetch();
27706
+ const existing = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId), Q17.where("path", normalized)).fetch();
27548
27707
  if (existing.length > 0) {
27549
27708
  await existing[0].update((f) => {
27550
27709
  f._setRaw("content", content);
@@ -27564,11 +27723,11 @@ async function putAppFileOp(ctx, conversationId, path, content) {
27564
27723
  }
27565
27724
  async function getAppFileOp(ctx, conversationId, path) {
27566
27725
  const normalized = normalizePath(path);
27567
- const results = await ctx.appFilesCollection.query(Q16.where("conversation_id", conversationId), Q16.where("path", normalized)).fetch();
27726
+ const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId), Q17.where("path", normalized)).fetch();
27568
27727
  return results.length > 0 ? appFileToStored(results[0]) : null;
27569
27728
  }
27570
27729
  async function getAppFilesOp(ctx, conversationId) {
27571
- const results = await ctx.appFilesCollection.query(Q16.where("conversation_id", conversationId)).fetch();
27730
+ const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId)).fetch();
27572
27731
  return results.map(appFileToStored);
27573
27732
  }
27574
27733
  async function getAppFileMapOp(ctx, conversationId) {
@@ -27579,7 +27738,7 @@ async function getAppFileMapOp(ctx, conversationId) {
27579
27738
  }
27580
27739
  async function deleteAppFileOp(ctx, conversationId, path) {
27581
27740
  const normalized = normalizePath(path);
27582
- const results = await ctx.appFilesCollection.query(Q16.where("conversation_id", conversationId), Q16.where("path", normalized)).fetch();
27741
+ const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId), Q17.where("path", normalized)).fetch();
27583
27742
  if (results.length === 0) return false;
27584
27743
  await ctx.database.write(async () => {
27585
27744
  await results[0].destroyPermanently();
@@ -27587,7 +27746,7 @@ async function deleteAppFileOp(ctx, conversationId, path) {
27587
27746
  return true;
27588
27747
  }
27589
27748
  async function deleteAllAppFilesOp(ctx, conversationId) {
27590
- const results = await ctx.appFilesCollection.query(Q16.where("conversation_id", conversationId)).fetch();
27749
+ const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId)).fetch();
27591
27750
  if (results.length === 0) return;
27592
27751
  await ctx.database.write(async () => {
27593
27752
  const batch = results.map((file) => file.prepareDestroyPermanently());
@@ -27596,7 +27755,7 @@ async function deleteAllAppFilesOp(ctx, conversationId) {
27596
27755
  }
27597
27756
 
27598
27757
  // src/lib/db/conversationMemory/operations.ts
27599
- import { Q as Q17 } from "@nozbe/watermelondb";
27758
+ import { Q as Q18 } from "@nozbe/watermelondb";
27600
27759
  var MAX_PER_CONVERSATION = 200;
27601
27760
  function conversationMemoryToStored(row) {
27602
27761
  return {
@@ -27611,7 +27770,7 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
27611
27770
  if (!conversationId || items.length === 0) return;
27612
27771
  const now = Date.now();
27613
27772
  await ctx.database.write(async () => {
27614
- const existing = await ctx.conversationMemoryCollection.query(Q17.where("conversation_id", conversationId), Q17.sortBy("created_at", Q17.asc)).fetch();
27773
+ const existing = await ctx.conversationMemoryCollection.query(Q18.where("conversation_id", conversationId), Q18.sortBy("created_at", Q18.asc)).fetch();
27615
27774
  const seen = new Set(existing.map((r) => r.memoryId));
27616
27775
  const batchSeen = /* @__PURE__ */ new Set();
27617
27776
  const deduped = [];
@@ -27646,20 +27805,20 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
27646
27805
  }
27647
27806
  async function getConversationMemoriesOp(ctx, conversationId) {
27648
27807
  if (!conversationId) return [];
27649
- const rows = await ctx.conversationMemoryCollection.query(Q17.where("conversation_id", conversationId), Q17.sortBy("created_at", Q17.asc)).fetch();
27808
+ const rows = await ctx.conversationMemoryCollection.query(Q18.where("conversation_id", conversationId), Q18.sortBy("created_at", Q18.asc)).fetch();
27650
27809
  return rows.map(conversationMemoryToStored);
27651
27810
  }
27652
27811
  async function clearConversationMemoriesOp(ctx, conversationId) {
27653
27812
  if (!conversationId) return;
27654
27813
  await ctx.database.write(async () => {
27655
- const rows = await ctx.conversationMemoryCollection.query(Q17.where("conversation_id", conversationId)).fetch();
27814
+ const rows = await ctx.conversationMemoryCollection.query(Q18.where("conversation_id", conversationId)).fetch();
27656
27815
  if (rows.length === 0) return;
27657
27816
  await ctx.database.batch(...rows.map((r) => r.prepareDestroyPermanently()));
27658
27817
  });
27659
27818
  }
27660
27819
 
27661
27820
  // src/lib/db/savedTools/operations.ts
27662
- import { Q as Q18 } from "@nozbe/watermelondb";
27821
+ import { Q as Q19 } from "@nozbe/watermelondb";
27663
27822
  function savedToolToStored(tool) {
27664
27823
  return {
27665
27824
  uniqueId: tool.id,
@@ -27692,7 +27851,7 @@ async function createSavedToolOp(ctx, opts) {
27692
27851
  return savedToolToStored(created);
27693
27852
  }
27694
27853
  async function getAllSavedToolsOp(ctx) {
27695
- const results = await ctx.savedToolsCollection.query(Q18.where("is_deleted", false), Q18.sortBy("created_at", Q18.desc)).fetch();
27854
+ const results = await ctx.savedToolsCollection.query(Q19.where("is_deleted", false), Q19.sortBy("created_at", Q19.desc)).fetch();
27696
27855
  return results.map(savedToolToStored);
27697
27856
  }
27698
27857
  async function getSavedToolByIdOp(ctx, uniqueId) {
@@ -30348,8 +30507,8 @@ function createDropboxFileIndex(backupFolder) {
30348
30507
  };
30349
30508
  }
30350
30509
  async function readLocalUpdatedAt(database, conversationId) {
30351
- const { Q: Q19 } = await import("@nozbe/watermelondb");
30352
- const records = await database.get("conversations").query(Q19.where("conversation_id", conversationId)).fetch();
30510
+ const { Q: Q20 } = await import("@nozbe/watermelondb");
30511
+ const records = await database.get("conversations").query(Q20.where("conversation_id", conversationId)).fetch();
30353
30512
  const match = records.map(conversationToStoredRaw).find((c) => c.conversationId === conversationId);
30354
30513
  return match ? match.updatedAt : null;
30355
30514
  }
@@ -30405,9 +30564,9 @@ async function pushConversationToDropbox(database, conversationId, userAddress,
30405
30564
  }
30406
30565
  async function performDropboxExport(database, userAddress, token, deps, onProgress, backupFolder = DEFAULT_BACKUP_FOLDER) {
30407
30566
  await deps.requestEncryptionKey(userAddress);
30408
- const { Q: Q19 } = await import("@nozbe/watermelondb");
30567
+ const { Q: Q20 } = await import("@nozbe/watermelondb");
30409
30568
  const conversationsCollection = database.get("conversations");
30410
- const records = await conversationsCollection.query(Q19.where("is_deleted", false)).fetch();
30569
+ const records = await conversationsCollection.query(Q20.where("is_deleted", false)).fetch();
30411
30570
  const conversations = records.map(conversationToStoredRaw);
30412
30571
  const total = conversations.length;
30413
30572
  if (total === 0) {
@@ -31089,8 +31248,8 @@ function createDriveFileIndex(folderId) {
31089
31248
  };
31090
31249
  }
31091
31250
  async function readLocalUpdatedAt2(database, conversationId) {
31092
- const { Q: Q19 } = await import("@nozbe/watermelondb");
31093
- const records = await database.get("conversations").query(Q19.where("conversation_id", conversationId)).fetch();
31251
+ const { Q: Q20 } = await import("@nozbe/watermelondb");
31252
+ const records = await database.get("conversations").query(Q20.where("conversation_id", conversationId)).fetch();
31094
31253
  const match = records.map(conversationToStoredRaw).find((c) => c.conversationId === conversationId);
31095
31254
  return match ? match.updatedAt : null;
31096
31255
  }
@@ -31170,9 +31329,9 @@ async function performGoogleDriveExport(database, userAddress, token, deps, onPr
31170
31329
  }
31171
31330
  const { folderId, token: activeToken } = folderResult;
31172
31331
  const fileIndex = createDriveFileIndex(folderId);
31173
- const { Q: Q19 } = await import("@nozbe/watermelondb");
31332
+ const { Q: Q20 } = await import("@nozbe/watermelondb");
31174
31333
  const conversationsCollection = database.get("conversations");
31175
- const records = await conversationsCollection.query(Q19.where("is_deleted", false)).fetch();
31334
+ const records = await conversationsCollection.query(Q20.where("is_deleted", false)).fetch();
31176
31335
  const conversations = records.map(conversationToStoredRaw);
31177
31336
  const total = conversations.length;
31178
31337
  if (total === 0) {
@@ -31757,9 +31916,9 @@ async function pushConversationToICloud(database, conversationId, userAddress, d
31757
31916
  const filename = `${conversationId}.json`;
31758
31917
  const existingFile = await findICloudFile(filename);
31759
31918
  if (existingFile) {
31760
- const { Q: Q19 } = await import("@nozbe/watermelondb");
31919
+ const { Q: Q20 } = await import("@nozbe/watermelondb");
31761
31920
  const conversationsCollection = database.get("conversations");
31762
- const records = await conversationsCollection.query(Q19.where("conversation_id", conversationId)).fetch();
31921
+ const records = await conversationsCollection.query(Q20.where("conversation_id", conversationId)).fetch();
31763
31922
  if (records.length > 0) {
31764
31923
  const conversation = conversationToStoredRaw(records[0]);
31765
31924
  const localUpdated = conversation.updatedAt.getTime();
@@ -31789,9 +31948,9 @@ async function pushConversationToICloud(database, conversationId, userAddress, d
31789
31948
  }
31790
31949
  async function performICloudExport(database, userAddress, deps, onProgress) {
31791
31950
  await deps.requestEncryptionKey(userAddress);
31792
- const { Q: Q19 } = await import("@nozbe/watermelondb");
31951
+ const { Q: Q20 } = await import("@nozbe/watermelondb");
31793
31952
  const conversationsCollection = database.get("conversations");
31794
- const records = await conversationsCollection.query(Q19.where("is_deleted", false)).fetch();
31953
+ const records = await conversationsCollection.query(Q20.where("is_deleted", false)).fetch();
31795
31954
  const conversations = records.map(conversationToStoredRaw);
31796
31955
  const total = conversations.length;
31797
31956
  if (total === 0) {
@@ -35766,6 +35925,7 @@ export {
35766
35925
  createGitHubTools,
35767
35926
  createLlmDecayClassifier,
35768
35927
  createLlmNeighborRefiner,
35928
+ createLocalMemoryStore,
35769
35929
  createMediaBatchOp,
35770
35930
  createMediaOp,
35771
35931
  createMemoryEngineTool,