@anuma/sdk 3.1.3 → 3.2.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.
@@ -112,7 +112,7 @@ import {
112
112
  updateVaultMemoryOp,
113
113
  useEncryption,
114
114
  vaultMemoryToStored
115
- } from "./chunk-3KGACSSP.mjs";
115
+ } from "./chunk-Y7PMXJT6.mjs";
116
116
  import {
117
117
  PiiRedactor,
118
118
  createStreamingDeAnonymizer,
@@ -6831,6 +6831,9 @@ __decorateClass([
6831
6831
  __decorateClass([
6832
6832
  field3("topics_extracted_version")
6833
6833
  ], VaultMemory.prototype, "topicsExtractedVersion", 2);
6834
+ __decorateClass([
6835
+ field3("last_observed_at")
6836
+ ], VaultMemory.prototype, "lastObservedAt", 2);
6834
6837
  __decorateClass([
6835
6838
  readonly2,
6836
6839
  date3("created_at")
@@ -6897,6 +6900,8 @@ async function retain(content, ctx, options = {}) {
6897
6900
  proofCountIncrement: 1,
6898
6901
  sourceChunkIds: mergedSourceIds,
6899
6902
  preserveUpdatedAt: true,
6903
+ // C3: record the re-observation without touching updated_at.
6904
+ lastObservedAt: Date.now(),
6900
6905
  ...eventTimeUpdate && { eventTime: eventTimeUpdate }
6901
6906
  });
6902
6907
  if (updated) {
@@ -7047,6 +7052,8 @@ async function tryConsolidate(trimmed, ctx, options) {
7047
7052
  proofCountIncrement: 1,
7048
7053
  sourceChunkIds: mergedSourceIds,
7049
7054
  preserveUpdatedAt: true,
7055
+ // C3: record the re-observation without touching updated_at.
7056
+ lastObservedAt: Date.now(),
7050
7057
  ...eventTimeUpdate && { eventTime: eventTimeUpdate }
7051
7058
  });
7052
7059
  if (!updated) {
@@ -7083,6 +7090,8 @@ async function tryConsolidate(trimmed, ctx, options) {
7083
7090
  // one. Preserving updated_at keeps the recency multiplier honest
7084
7091
  // and matches the merge/noop paths above.
7085
7092
  preserveUpdatedAt: true,
7093
+ // C3: record the re-observation without touching updated_at.
7094
+ lastObservedAt: Date.now(),
7086
7095
  ...eventTimeUpdate && { eventTime: eventTimeUpdate }
7087
7096
  });
7088
7097
  if (!updated) {
@@ -7886,6 +7895,311 @@ function parseAnswer(body, base, parseSchema) {
7886
7895
  };
7887
7896
  }
7888
7897
 
7898
+ // src/lib/memory/synthesizeProfile.ts
7899
+ var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
7900
+ var DEFAULT_FACET_RECALL_LIMIT = 20;
7901
+ var DEFAULT_FACET_MAX_TOKENS = 512;
7902
+ var DEFAULT_SCOPES = ["private"];
7903
+ var NEW_FACT_ATTRIBUTION_MIN_SCORE = 0.1;
7904
+ var PROFILE_DOC_VERSION = 1;
7905
+ var DEFAULT_PROFILE_FACETS = [
7906
+ {
7907
+ key: "bio",
7908
+ label: "Bio",
7909
+ query: "Who is this person? Their background, personality, values, and what defines them.",
7910
+ guidance: "Write a 1-2 sentence bio (max ~40 words) that captures what makes this person distinctive \u2014 their character, values, or a defining thread across the memories. Be specific and grounded; ban generic dating clich\xE9s ('loves to laugh', 'foodie', 'work hard play hard', 'living life to the fullest')."
7911
+ },
7912
+ {
7913
+ key: "interests",
7914
+ label: "Interests",
7915
+ query: "What are this person's hobbies, passions, pastimes, and interests?",
7916
+ guidance: "Return 3-6 specific interests as a comma-separated list (e.g. 'trail running, film photography, Thai cooking'). Prefer concrete activities the memories actually show over broad categories ('music', 'travel'). No sentence, just the list."
7917
+ },
7918
+ {
7919
+ key: "work_role",
7920
+ label: "Work & Role",
7921
+ query: "What does this person do for work \u2014 their profession, role, industry, or studies?",
7922
+ guidance: "State the person's current role/profession and field in one short line (e.g. 'Backend engineer at a fintech startup'). Use only what the memories support; if unclear or absent, return hasEvidence=false rather than guessing a title."
7923
+ },
7924
+ {
7925
+ key: "location_context",
7926
+ label: "Location",
7927
+ query: "Where does this person live, spend time, or come from?",
7928
+ guidance: "Summarize where the person is based or spends time at neighborhood-or-city granularity in one short line (e.g. 'Based in the Mission, SF'). PRIVACY: never emit a precise address, building, or workplace location \u2014 coarse-grain to the city/neighborhood."
7929
+ },
7930
+ {
7931
+ key: "communication_style",
7932
+ label: "Communication Style",
7933
+ query: "How does this person communicate, express themselves, and interact with others?",
7934
+ guidance: "Describe the person's communication and social style in one line using 2-4 concrete adjectives grounded in the memories (e.g. 'Direct, dry-humored, and a careful listener'). Avoid empty praise."
7935
+ },
7936
+ {
7937
+ key: "recent_activity",
7938
+ label: "Recently",
7939
+ query: "What has this person been doing, focused on, or working on recently?",
7940
+ guidance: "Summarize what the person has been up to lately in one line, favoring the most recently reinforced facts. Frame it as current/ongoing (e.g. 'Lately: training for a first half-marathon and learning Portuguese'). Omit if nothing recent stands out."
7941
+ }
7942
+ ];
7943
+ var FACET_RESPONSE_SCHEMA = {
7944
+ type: "object",
7945
+ properties: {
7946
+ summary: {
7947
+ type: "string",
7948
+ description: "The synthesized section prose. Empty string if the memories don't cover it."
7949
+ },
7950
+ hasEvidence: {
7951
+ type: "boolean",
7952
+ description: "False when the supplied memories don't support any claim for this facet."
7953
+ }
7954
+ },
7955
+ required: ["summary", "hasEvidence"],
7956
+ additionalProperties: false
7957
+ };
7958
+ async function synthesizeProfile(ctx, options = {}) {
7959
+ if (!ctx.vaultCtx) {
7960
+ throw new Error("synthesizeProfile requires ctx.vaultCtx (vault-backed facts).");
7961
+ }
7962
+ if (!ctx.vaultCache) {
7963
+ throw new Error("synthesizeProfile requires ctx.vaultCache (semantic fact recall).");
7964
+ }
7965
+ const facets = options.facets ?? DEFAULT_PROFILE_FACETS;
7966
+ const scopes = options.scopes ?? DEFAULT_SCOPES;
7967
+ const config = {
7968
+ facetKeys: facets.map((f) => f.key).sort(),
7969
+ facetsSignature: facetsSignature(facets),
7970
+ scopes: [...scopes].sort(),
7971
+ redacted: options.redactor !== void 0
7972
+ };
7973
+ const previous = options.previous && options.previous.version === PROFILE_DOC_VERSION && configMatches(options.previous.config, config) ? options.previous : void 0;
7974
+ const memories = await getAllVaultMemoriesOp(ctx.vaultCtx, {
7975
+ // Scope the snapshot to the same scopes synthesis recalls from, so the
7976
+ // watermark, delta, and new-fact attribution all track only facts that can
7977
+ // actually appear in the profile — an out-of-scope change/new-fact must not
7978
+ // trigger a regeneration that scoped recall would never reflect.
7979
+ scopes,
7980
+ includeDeleted: true,
7981
+ includeSuperseded: true
7982
+ });
7983
+ const watermark = computeVaultWatermark(memories);
7984
+ const presentIds = new Set(memories.map((m) => m.uniqueId));
7985
+ const hasStaleSections = previous?.sections.some((s) => s.stale);
7986
+ const citesMissingFact = previous?.sections.some(
7987
+ (s) => s.sourceMemoryIds.some((id) => !presentIds.has(id))
7988
+ );
7989
+ if (previous && previous.vaultWatermark === watermark && !hasStaleSections && !citesMissingFact) {
7990
+ const sameOrder = previous.sections.length === facets.length && facets.every((f, i) => previous.sections[i]?.key === f.key);
7991
+ if (sameOrder) return previous;
7992
+ return {
7993
+ ...previous,
7994
+ sections: facets.map((f) => previous.sections.find((s) => s.key === f.key))
7995
+ };
7996
+ }
7997
+ const staleKeys = await computeStaleFacetKeys(ctx, memories, facets, previous, watermark);
7998
+ const settled = await Promise.allSettled(
7999
+ facets.map(async (facet) => {
8000
+ const prior = previous?.sections.find((s) => s.key === facet.key);
8001
+ if (prior && !staleKeys.has(facet.key)) {
8002
+ return prior;
8003
+ }
8004
+ return synthesizeFacet(facet, ctx, options, prior);
8005
+ })
8006
+ );
8007
+ const sections = settled.map((r, i) => {
8008
+ if (r.status === "fulfilled") return r.value;
8009
+ const facet = facets[i];
8010
+ getLogger().warn(
8011
+ "[memory/synthesizeProfile] facet synthesis rejected; using fallback section",
8012
+ {
8013
+ facet: facet.key,
8014
+ error: r.reason instanceof Error ? r.reason.message : String(r.reason)
8015
+ }
8016
+ );
8017
+ return fallbackSection(
8018
+ facet,
8019
+ previous?.sections.find((s) => s.key === facet.key)
8020
+ );
8021
+ });
8022
+ return {
8023
+ version: PROFILE_DOC_VERSION,
8024
+ sections,
8025
+ vaultWatermark: watermark,
8026
+ config,
8027
+ generatedAt: Date.now()
8028
+ };
8029
+ }
8030
+ function configMatches(a, b) {
8031
+ if (!a) return false;
8032
+ return a.redacted === b.redacted && a.facetsSignature === b.facetsSignature && a.scopes.length === b.scopes.length && a.scopes.every((s, i) => s === b.scopes[i]);
8033
+ }
8034
+ function facetsSignature(facets) {
8035
+ return facets.map((f) => JSON.stringify([f.key, f.label, f.query, f.guidance])).sort().join("\n");
8036
+ }
8037
+ function changeTime(m) {
8038
+ return Math.max(m.updatedAt.getTime(), m.supersededAt ?? 0, m.lastObservedAt ?? 0);
8039
+ }
8040
+ function computeVaultWatermark(memories) {
8041
+ let max = 0;
8042
+ for (const m of memories) {
8043
+ const t = changeTime(m);
8044
+ if (t > max) max = t;
8045
+ }
8046
+ return max;
8047
+ }
8048
+ async function computeStaleFacetKeys(ctx, memories, facets, previous, watermark) {
8049
+ const allKeys = new Set(facets.map((f) => f.key));
8050
+ if (previous && watermark < previous.vaultWatermark) return allKeys;
8051
+ if (!previous) return allKeys;
8052
+ const changed = memories.filter((m) => changeTime(m) > previous.vaultWatermark);
8053
+ const changedIds = new Set(changed.map((m) => m.uniqueId));
8054
+ const presentIds = new Set(memories.map((m) => m.uniqueId));
8055
+ const stale = /* @__PURE__ */ new Set();
8056
+ for (const section of previous.sections) {
8057
+ if (section.sourceMemoryIds.some((id) => changedIds.has(id))) {
8058
+ stale.add(section.key);
8059
+ }
8060
+ if (section.sourceMemoryIds.some((id) => !presentIds.has(id))) {
8061
+ stale.add(section.key);
8062
+ }
8063
+ if (section.stale) {
8064
+ stale.add(section.key);
8065
+ }
8066
+ }
8067
+ for (const facet of facets) {
8068
+ if (!previous.sections.some((s) => s.key === facet.key)) stale.add(facet.key);
8069
+ }
8070
+ const citedIds = new Set(previous.sections.flatMap((s) => s.sourceMemoryIds));
8071
+ const toAttribute = changed.filter(
8072
+ (m) => !m.isDeleted && !m.supersededBy && !citedIds.has(m.uniqueId)
8073
+ );
8074
+ if (toAttribute.length > 0) {
8075
+ const attributed = await attributeFacts(ctx, toAttribute, facets);
8076
+ if (attributed === null) return allKeys;
8077
+ for (const k of attributed) stale.add(k);
8078
+ }
8079
+ return stale;
8080
+ }
8081
+ async function attributeFacts(ctx, candidates, facets) {
8082
+ const model = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
8083
+ const factVectors = [];
8084
+ for (const f of candidates) {
8085
+ if (!f.embedding || f.embeddingModel && f.embeddingModel !== model) {
8086
+ getLogger().warn(
8087
+ "[memory/synthesizeProfile] fact lacks a usable current-model embedding; regenerating all facets",
8088
+ { memoryId: f.uniqueId, hasEmbedding: !!f.embedding, embeddingModel: f.embeddingModel }
8089
+ );
8090
+ return null;
8091
+ }
8092
+ let vec;
8093
+ try {
8094
+ vec = JSON.parse(f.embedding);
8095
+ } catch {
8096
+ getLogger().warn(
8097
+ "[memory/synthesizeProfile] fact embedding failed to parse; regenerating all facets",
8098
+ { memoryId: f.uniqueId }
8099
+ );
8100
+ return null;
8101
+ }
8102
+ if (!Array.isArray(vec) || vec.length === 0) return null;
8103
+ factVectors.push(vec);
8104
+ }
8105
+ let queryVectors;
8106
+ try {
8107
+ queryVectors = await generateEmbeddings(
8108
+ facets.map((f) => f.query),
8109
+ ctx.embeddingOptions
8110
+ );
8111
+ } catch (err) {
8112
+ getLogger().warn(
8113
+ "[memory/synthesizeProfile] facet-query embedding failed; regenerating all facets",
8114
+ { error: err instanceof Error ? err.message : String(err) }
8115
+ );
8116
+ return null;
8117
+ }
8118
+ const keys = /* @__PURE__ */ new Set();
8119
+ for (const fv of factVectors) {
8120
+ let matchedAny = false;
8121
+ for (let i = 0; i < facets.length; i++) {
8122
+ if (cosineSimilarity(fv, queryVectors[i]) >= NEW_FACT_ATTRIBUTION_MIN_SCORE) {
8123
+ keys.add(facets[i].key);
8124
+ matchedAny = true;
8125
+ }
8126
+ }
8127
+ if (!matchedAny) return null;
8128
+ }
8129
+ return keys;
8130
+ }
8131
+ async function synthesizeFacet(facet, ctx, options, prior) {
8132
+ const result = await reflect(facet.query, ctx, {
8133
+ apiKey: options.apiKey,
8134
+ getToken: options.getToken,
8135
+ llmModel: options.llmModel ?? DEFAULT_SYNTHESIS_MODEL,
8136
+ baseUrl: options.baseUrl,
8137
+ fetchFn: options.fetchFn,
8138
+ scopes: options.scopes ?? DEFAULT_SCOPES,
8139
+ limit: options.limit ?? DEFAULT_FACET_RECALL_LIMIT,
8140
+ types: ["fact"],
8141
+ maxTokens: DEFAULT_FACET_MAX_TOKENS,
8142
+ systemPrompt: buildFacetSystemPrompt(facet),
8143
+ responseSchema: FACET_RESPONSE_SCHEMA
8144
+ });
8145
+ const noEvidence = result.basedOn.memoryIds.length === 0;
8146
+ const { text: text12, legitimateEmpty } = extractFacetText(result.structuredOutput);
8147
+ if (!text12 && !legitimateEmpty && !noEvidence) {
8148
+ getLogger().warn(
8149
+ "[memory/synthesizeProfile] facet synthesis returned degraded-empty; keeping prior section",
8150
+ { facet: facet.key, recalledCount: result.basedOn.memoryIds.length }
8151
+ );
8152
+ return fallbackSection(facet, prior);
8153
+ }
8154
+ const section = {
8155
+ key: facet.key,
8156
+ label: facet.label,
8157
+ text: text12,
8158
+ sourceMemoryIds: result.basedOn.memoryIds,
8159
+ generatedAt: Date.now()
8160
+ };
8161
+ if (options.redactor && text12) {
8162
+ const redacted = await options.redactor.redactTextAsync(text12);
8163
+ section.text = redacted.text;
8164
+ }
8165
+ return section;
8166
+ }
8167
+ function fallbackSection(facet, prior) {
8168
+ if (prior && prior.text) {
8169
+ return { ...prior, stale: true };
8170
+ }
8171
+ return {
8172
+ key: facet.key,
8173
+ label: facet.label,
8174
+ text: "",
8175
+ sourceMemoryIds: [],
8176
+ generatedAt: Date.now(),
8177
+ stale: true
8178
+ };
8179
+ }
8180
+ function buildFacetSystemPrompt(facet) {
8181
+ return `You are writing the "${facet.label}" section of a person's shareable profile, using their private memories (supplied as evidence) as the only source of truth.
8182
+
8183
+ Task for this section:
8184
+ ${facet.guidance}
8185
+
8186
+ Rules:
8187
+ - Ground every claim in the supplied memories \u2014 never invent, infer beyond, or embellish what they support.
8188
+ - If the memories don't cover this section, return an empty summary with hasEvidence=false. Do not pad or guess.
8189
+ - Write in third person about the person, in a natural voice suitable for a public profile (no "I"/"you", no name repetition).
8190
+ - Be concise and specific; no preamble, hedging, or meta-commentary.
8191
+ - Respond as JSON: { "summary": <the section text, or "">, "hasEvidence": <true|false> }.`;
8192
+ }
8193
+ function extractFacetText(structured) {
8194
+ if (structured && typeof structured === "object") {
8195
+ const obj = structured;
8196
+ if (obj.hasEvidence === false) return { text: "", legitimateEmpty: true };
8197
+ if (typeof obj.summary === "string")
8198
+ return { text: obj.summary.trim(), legitimateEmpty: false };
8199
+ }
8200
+ return { text: "", legitimateEmpty: false };
8201
+ }
8202
+
7889
8203
  // src/lib/memory/topicExtract.ts
7890
8204
  var TOPIC_EXTRACTION_BATCH_SIZE = 10;
7891
8205
  var MAX_CHARS_PER_MEMORY = 300;
@@ -12460,7 +12774,7 @@ __decorateClass([
12460
12774
  ], VaultFolder.prototype, "context", 2);
12461
12775
 
12462
12776
  // src/lib/db/schema.ts
12463
- var SDK_SCHEMA_VERSION = 38;
12777
+ var SDK_SCHEMA_VERSION = 39;
12464
12778
  var sdkSchema = appSchema2({
12465
12779
  version: SDK_SCHEMA_VERSION,
12466
12780
  tables: [
@@ -12598,7 +12912,14 @@ var sdkSchema = appSchema2({
12598
12912
  // The extraction-logic version this memory was last stamped under. Null
12599
12913
  // (pre-v38) is treated as version 0, so a bump of TOPICS_EXTRACTION_VERSION
12600
12914
  // re-extracts stale rows. See getMemoriesNeedingTopicExtractionOp.
12601
- { name: "topics_extracted_version", type: "number", isOptional: true }
12915
+ { name: "topics_extracted_version", type: "number", isOptional: true },
12916
+ // Re-observation watermark (C3). Unix ms of the last time retain() merged
12917
+ // a duplicate observation into this fact (proof_count++). Distinct from
12918
+ // updated_at, which merges deliberately preserve (preserveUpdatedAt) so a
12919
+ // re-observation doesn't reorder the vault by edit time. Null = never
12920
+ // re-observed since the column was added. Indexed so recency-weighted
12921
+ // synthesis can filter/sort on it cheaply.
12922
+ { name: "last_observed_at", type: "number", isOptional: true, isIndexed: true }
12602
12923
  ]
12603
12924
  }),
12604
12925
  // Entity table — canonical names extracted from auto-extraction (W5).
@@ -13237,6 +13558,20 @@ var sdkMigrations = schemaMigrations2({
13237
13558
  columns: [{ name: "topics_extracted_version", type: "number", isOptional: true }]
13238
13559
  })
13239
13560
  ]
13561
+ },
13562
+ // v38 -> v39: re-observation watermark on memory_vault (C3). Existing rows
13563
+ // keep NULL (= never re-observed since the column was added); synthesis
13564
+ // treats NULL as "fall back to updated_at" so no backfill is needed.
13565
+ {
13566
+ toVersion: 39,
13567
+ steps: [
13568
+ addColumns2({
13569
+ table: "memory_vault",
13570
+ columns: [
13571
+ { name: "last_observed_at", type: "number", isOptional: true, isIndexed: true }
13572
+ ]
13573
+ })
13574
+ ]
13240
13575
  }
13241
13576
  ]
13242
13577
  });
@@ -23666,6 +24001,7 @@ export {
23666
24001
  DEFAULT_BACKUP_FOLDER2 as DEFAULT_ICLOUD_BACKUP_FOLDER,
23667
24002
  DEFAULT_MIN_CHUNK_SIZE,
23668
24003
  DEFAULT_PERSONALITY_SETTINGS,
24004
+ DEFAULT_PROFILE_FACETS,
23669
24005
  DEFAULT_SERVER_TOOLS_MATCH_OPTIONS,
23670
24006
  DEFAULT_VAULT_CACHE_SIZE,
23671
24007
  DatabaseManager,
@@ -23680,6 +24016,7 @@ export {
23680
24016
  INFERENCE_ID_HEADER,
23681
24017
  LoggerProvider,
23682
24018
  MemoryEntity as MemoryEntityModel,
24019
+ PROFILE_DOC_VERSION,
23683
24020
  PdfProcessor,
23684
24021
  ProcessorRegistry,
23685
24022
  Project,
@@ -23983,6 +24320,7 @@ export {
23983
24320
  streamCancelPath,
23984
24321
  streamReplayPath,
23985
24322
  supersedeVaultMemoryOp,
24323
+ synthesizeProfile,
23986
24324
  updateAttrs,
23987
24325
  updateConversationProjectOp,
23988
24326
  updateMediaMessageIdBatchOp,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-3KGACSSP.mjs";
3
+ } from "./chunk-Y7PMXJT6.mjs";
4
4
  import "./chunk-DFVCS3QQ.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {
@@ -16238,6 +16238,7 @@ function vaultMemoryToStoredRaw(memory) {
16238
16238
  topicsExtractedVersion: memory.topicsExtractedVersion ?? null,
16239
16239
  supersededBy: memory.supersededBy ?? null,
16240
16240
  supersededAt: memory.supersededAt ?? null,
16241
+ lastObservedAt: memory.lastObservedAt ?? null,
16241
16242
  createdAt: memory.createdAt,
16242
16243
  updatedAt: memory.updatedAt,
16243
16244
  isDeleted: memory.isDeleted
@@ -16478,6 +16479,7 @@ function vaultMemoryRawToStoredRaw(raw) {
16478
16479
  topicsExtractedVersion: raw.topics_extracted_version ?? null,
16479
16480
  supersededBy: raw.superseded_by ?? null,
16480
16481
  supersededAt: raw.superseded_at ?? null,
16482
+ lastObservedAt: raw.last_observed_at ?? null,
16481
16483
  createdAt: new Date(raw.created_at),
16482
16484
  updatedAt: new Date(raw.updated_at),
16483
16485
  isDeleted: raw.is_deleted === true || raw.is_deleted === 1
@@ -16566,6 +16568,9 @@ async function updateVaultMemoryOp(ctx, id, opts) {
16566
16568
  if (opts.topicsUserManaged !== void 0) {
16567
16569
  r._setRaw("topics_user_managed", opts.topicsUserManaged);
16568
16570
  }
16571
+ if (opts.lastObservedAt !== void 0) {
16572
+ r._setRaw("last_observed_at", opts.lastObservedAt);
16573
+ }
16569
16574
  if (opts.preserveUpdatedAt) {
16570
16575
  r._setRaw("updated_at", originalUpdatedAt);
16571
16576
  }
@@ -18524,7 +18529,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
18524
18529
  legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
18525
18530
  );
18526
18531
  }
18527
- const { recall: recall2 } = await import("./recall-2K7IOKY3.mjs");
18532
+ const { recall: recall2 } = await import("./recall-Z72DM2JK.mjs");
18528
18533
  const result = await recall2(
18529
18534
  query,
18530
18535
  { vaultCtx, embeddingOptions, vaultCache: cache },