@anuma/sdk 3.12.2 → 3.13.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.
@@ -20,6 +20,7 @@ import {
20
20
  VAULT_SIZE_HOP_CAP,
21
21
  archiveVaultMemoryOp,
22
22
  assertVaultScopeForSweep,
23
+ backfillMemoryTopicsOp,
23
24
  capHopsForDensity,
24
25
  chunkAndEmbedAllMessages,
25
26
  chunkAndEmbedMessage,
@@ -91,6 +92,7 @@ import {
91
92
  prepareVaultCandidates,
92
93
  rankPreparedVaultCandidates,
93
94
  recall,
95
+ relinkMemoryTopicsOp,
94
96
  replaceMemoryEntitiesGuardedOp,
95
97
  requestEncryptionKey,
96
98
  resolveStoredUserContent,
@@ -114,7 +116,7 @@ import {
114
116
  upsertMessageOp,
115
117
  useEncryption,
116
118
  vaultMemoryToStored
117
- } from "./chunk-ORVYPS3R.mjs";
119
+ } from "./chunk-BOAKGY4R.mjs";
118
120
  import {
119
121
  PII_PATTERNS,
120
122
  PiiRedactor,
@@ -5596,6 +5598,12 @@ __decorateClass([
5596
5598
  __decorateClass([
5597
5599
  field3("topics_user_managed")
5598
5600
  ], VaultMemory.prototype, "topicsUserManaged", 2);
5601
+ __decorateClass([
5602
+ field3("topics")
5603
+ ], VaultMemory.prototype, "topics", 2);
5604
+ __decorateClass([
5605
+ field3("topics_updated_at")
5606
+ ], VaultMemory.prototype, "topicsUpdatedAt", 2);
5599
5607
  __decorateClass([
5600
5608
  field3("topics_extracted_at")
5601
5609
  ], VaultMemory.prototype, "topicsExtractedAt", 2);
@@ -10831,6 +10839,31 @@ function useChatStorage(options) {
10831
10839
  };
10832
10840
  }
10833
10841
  const { callRedactor, callPiiRedaction, maskForCall } = resolvePiiForCall(convId);
10842
+ const effectiveApiType = resolveApiType(requestApiType ?? apiType ?? "auto", model);
10843
+ const isServerToolsFunction = typeof serverToolsFilter === "function";
10844
+ const fetchServerToolsSettled = async (token) => {
10845
+ try {
10846
+ return {
10847
+ tools: await getServerTools({
10848
+ baseUrl,
10849
+ cacheExpirationMs: serverToolsConfig?.cacheExpirationMs,
10850
+ getToken: token,
10851
+ cache: serverToolsConfig?.cache
10852
+ })
10853
+ };
10854
+ } catch (error) {
10855
+ return { error };
10856
+ }
10857
+ };
10858
+ const embedForToolsSettled = async (token) => {
10859
+ try {
10860
+ return { embedding: await embedToolText(contentForStorage, maskForCall, token) };
10861
+ } catch (error) {
10862
+ return { error };
10863
+ }
10864
+ };
10865
+ const serverToolsPromise = getTokenRef.current && !(Array.isArray(serverToolsFilter) && serverToolsFilter.length === 0) ? fetchServerToolsSettled(getTokenRef.current) : null;
10866
+ const userMessageEmbeddingPromise = getTokenRef.current && contentForStorage.length >= MIN_CONTENT_LENGTH_FOR_TOOLS && (isServerToolsFunction && !(serverToolsConfig?.deferLoading?.enabled && effectiveApiType === "responses") || !!clientTools?.length) ? embedForToolsSettled(getTokenRef.current) : null;
10834
10867
  let messagesToSend;
10835
10868
  const storedMessages = await getMessages(convId);
10836
10869
  const knownToolCallEventIds = /* @__PURE__ */ new Set();
@@ -10905,29 +10938,26 @@ function useChatStorage(options) {
10905
10938
  };
10906
10939
  }
10907
10940
  const startTime = Date.now();
10908
- const effectiveApiType = resolveApiType(requestApiType ?? apiType ?? "auto", model);
10909
10941
  let mergedTools = clientTools;
10910
10942
  let userMessageEmbedding;
10911
10943
  let userMessageEmbeddingFailed = false;
10944
+ let serverFilterEmbeddingFailed = false;
10912
10945
  let filteredServerTools = [];
10913
- const isServerToolsFunction = typeof serverToolsFilter === "function";
10914
10946
  if (getTokenRef.current && !(Array.isArray(serverToolsFilter) && serverToolsFilter.length === 0)) {
10915
10947
  try {
10916
- const allServerTools = await getServerTools({
10917
- baseUrl,
10918
- cacheExpirationMs: serverToolsConfig?.cacheExpirationMs,
10919
- getToken: getTokenRef.current,
10920
- cache: serverToolsConfig?.cache
10921
- });
10948
+ const settledTools = await (serverToolsPromise ?? fetchServerToolsSettled(getTokenRef.current));
10949
+ if ("error" in settledTools) throw settledTools.error;
10950
+ const allServerTools = settledTools.tools;
10922
10951
  if (serverToolsConfig?.deferLoading?.enabled && effectiveApiType === "responses") {
10923
10952
  filteredServerTools = allServerTools;
10924
10953
  } else if (isServerToolsFunction) {
10925
10954
  if (contentForStorage.length >= MIN_CONTENT_LENGTH_FOR_TOOLS) {
10926
- userMessageEmbedding = await embedToolText(
10927
- contentForStorage,
10928
- maskForCall,
10929
- getTokenRef.current
10930
- );
10955
+ const settledEmbedding = await (userMessageEmbeddingPromise ?? embedForToolsSettled(getTokenRef.current));
10956
+ if ("error" in settledEmbedding) {
10957
+ serverFilterEmbeddingFailed = true;
10958
+ throw settledEmbedding.error;
10959
+ }
10960
+ userMessageEmbedding = settledEmbedding.embedding;
10931
10961
  const toolNames = serverToolsFilter(userMessageEmbedding, allServerTools);
10932
10962
  filteredServerTools = filterServerTools(allServerTools, toolNames);
10933
10963
  }
@@ -10951,14 +10981,11 @@ function useChatStorage(options) {
10951
10981
  if (clientTools?.length) {
10952
10982
  try {
10953
10983
  if (!userMessageEmbedding && getTokenRef.current && contentForStorage.length >= MIN_CONTENT_LENGTH_FOR_TOOLS) {
10954
- try {
10955
- userMessageEmbedding = await embedToolText(
10956
- contentForStorage,
10957
- maskForCall,
10958
- getTokenRef.current
10959
- );
10960
- } catch {
10984
+ const settledEmbedding = !userMessageEmbeddingPromise || serverFilterEmbeddingFailed ? await embedForToolsSettled(getTokenRef.current) : await userMessageEmbeddingPromise;
10985
+ if ("error" in settledEmbedding) {
10961
10986
  userMessageEmbeddingFailed = true;
10987
+ } else {
10988
+ userMessageEmbedding = settledEmbedding.embedding;
10962
10989
  }
10963
10990
  }
10964
10991
  if (typeof clientToolsFilter === "function") {
@@ -11773,7 +11800,7 @@ __decorateClass([
11773
11800
  ], VaultFolder.prototype, "context", 2);
11774
11801
 
11775
11802
  // src/lib/db/schema.ts
11776
- var SDK_SCHEMA_VERSION = 41;
11803
+ var SDK_SCHEMA_VERSION = 42;
11777
11804
  var sdkSchema = appSchema2({
11778
11805
  version: SDK_SCHEMA_VERSION,
11779
11806
  tables: [
@@ -11895,9 +11922,33 @@ var sdkSchema = appSchema2({
11895
11922
  // links). Auto-extraction then leaves its links alone — the user owns
11896
11923
  // them. Null/false = topics are auto-derived (default).
11897
11924
  { name: "topics_user_managed", type: "boolean", isOptional: true },
11925
+ // The memory's topics as a DURABLE, SYNCED record: a JSON array of
11926
+ // `{name, kind?, source}`, `name` in the caller's display casing (unlike
11927
+ // `entity.canonical_name`, which is lowercased and has no display
11928
+ // column). `entity` / `memory_entity` are a device-local INDEX over this
11929
+ // — their ids are locally generated, so they can never sync — and a
11930
+ // restored device rebuilds them from these names with no LLM call.
11931
+ // Null = predates v42 (backfilled from the row's current links by the
11932
+ // sweep's topicsBackfill bucket). See getMemoriesNeedingTopicExtractionOp.
11933
+ { name: "topics", type: "string", isOptional: true },
11934
+ // Unix ms of the last write to `topics`. A SECOND timestamp is required:
11935
+ // every topic writer deliberately pins `updated_at` so a topic change
11936
+ // doesn't inflate recall's recency multiplier, and both client sync
11937
+ // paths key on `updated_at` — so without this a topic-only change would
11938
+ // neither upload nor merge. Null = `topics` never written.
11939
+ { name: "topics_updated_at", type: "number", isOptional: true },
11898
11940
  // Unix ms of the last LLM topic-extraction pass over this memory's
11899
11941
  // content. Null = never extracted standalone (legacy rows with entity
11900
11942
  // links are grandfathered — see getMemoriesNeedingTopicExtractionOp).
11943
+ //
11944
+ // DEPRECATED (v42) — `topics_updated_at` subsumes this and
11945
+ // `topics_extracted_version` both: null there means never processed, and
11946
+ // non-null with an empty `topics` means processed and found nothing
11947
+ // (today's "answered empty" case), while a release-time
11948
+ // EXTRACTOR_CHANGED_AT constant compared against `topics_updated_at`
11949
+ // replaces the version check. Both columns are kept only to avoid a
11950
+ // column-drop migration in an otherwise additive list; removing them is
11951
+ // a follow-up once `topics` is proven in production.
11901
11952
  { name: "topics_extracted_at", type: "number", isOptional: true },
11902
11953
  // Write-time supersession (A2). When set, this fact was replaced by a
11903
11954
  // newer, incompatible-value fact (e.g. "Lives in Portland" superseded by
@@ -11911,6 +11962,9 @@ var sdkSchema = appSchema2({
11911
11962
  // The extraction-logic version this memory was last stamped under. Null
11912
11963
  // (pre-v38) is treated as version 0, so a bump of TOPICS_EXTRACTION_VERSION
11913
11964
  // re-extracts stale rows. See getMemoriesNeedingTopicExtractionOp.
11965
+ //
11966
+ // DEPRECATED (v42) alongside `topics_extracted_at` — same rationale and
11967
+ // same removal follow-up; see that column's note above.
11914
11968
  { name: "topics_extracted_version", type: "number", isOptional: true },
11915
11969
  // Re-observation watermark (C3). Unix ms of the last time retain() merged
11916
11970
  // a duplicate observation into this fact (proof_count++). Distinct from
@@ -12644,6 +12698,23 @@ var sdkMigrations = schemaMigrations2({
12644
12698
  ]
12645
12699
  })
12646
12700
  ]
12701
+ },
12702
+ // v41 -> v42: topics + topics_updated_at on memory_vault — the durable,
12703
+ // synced record of a memory's topics. Existing rows keep both NULL: the
12704
+ // sweep's topicsBackfill bucket fills them from each row's current entity
12705
+ // links (no LLM), capped under the worker's `limit` so the one-time
12706
+ // re-upload it triggers drains across sweeps instead of spiking.
12707
+ {
12708
+ toVersion: 42,
12709
+ steps: [
12710
+ addColumns2({
12711
+ table: "memory_vault",
12712
+ columns: [
12713
+ { name: "topics", type: "string", isOptional: true },
12714
+ { name: "topics_updated_at", type: "number", isOptional: true }
12715
+ ]
12716
+ })
12717
+ ]
12647
12718
  }
12648
12719
  ]
12649
12720
  });
@@ -14024,6 +14095,7 @@ export {
14024
14095
  WalletPoller,
14025
14096
  addConversationMemoriesOp,
14026
14097
  archiveVaultMemoryOp,
14098
+ backfillMemoryTopicsOp,
14027
14099
  buildNotionAuthUrl,
14028
14100
  capHopsForDensity,
14029
14101
  chatStorageMigrations,
@@ -14121,6 +14193,7 @@ export {
14121
14193
  reflect,
14122
14194
  refreshNotionAccessToken,
14123
14195
  registerNotionClient,
14196
+ relinkMemoryTopicsOp,
14124
14197
  requestEncryptionKey,
14125
14198
  resolvePiiRedactor,
14126
14199
  restoreVaultMemoryOp,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-ORVYPS3R.mjs";
3
+ } from "./chunk-BOAKGY4R.mjs";
4
4
  import "./chunk-ILAWDQDE.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {