@anuma/sdk 10.4.3 → 10.5.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.
@@ -1736,6 +1736,7 @@ __export(index_exports, {
1736
1736
  isSupportedFile: () => isSupportedFile,
1737
1737
  isSupportedMediaType: () => isSupportedMediaType,
1738
1738
  linkMemoryEntitiesOp: () => linkMemoryEntitiesOp,
1739
+ loadSettings: () => loadSettings,
1739
1740
  localChatBackend: () => localChatBackend,
1740
1741
  maskScopedEmbeddingCache: () => maskScopedEmbeddingCache,
1741
1742
  maxVaultAttachmentBytes: () => maxVaultAttachmentBytes,
@@ -1783,6 +1784,7 @@ __export(index_exports, {
1783
1784
  resumeStream: () => resumeStream,
1784
1785
  retain: () => retain,
1785
1786
  revokeNotionAccess: () => revokeNotionAccess,
1787
+ saveSetting: () => saveSetting,
1786
1788
  savedToolToStored: () => savedToolToStored,
1787
1789
  scoreProfileSalience: () => scoreProfileSalience,
1788
1790
  screenCandidatesForInjection: () => screenCandidatesForInjection,
@@ -13497,7 +13499,7 @@ var ChatStoreError = class extends Error {
13497
13499
  };
13498
13500
 
13499
13501
  // src/lib/chatStore/remote.ts
13500
- var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links"]);
13502
+ var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links", "setting"]);
13501
13503
  var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
13502
13504
  var maxPayload = 2 * 1024 * 1024;
13503
13505
  var storedDims2 = 1536;
@@ -13553,9 +13555,12 @@ function validRecord(value) {
13553
13555
  (key3) => ![...metadata, "data"].includes(key3)
13554
13556
  ))
13555
13557
  return false;
13556
- const root = value.kind === "conversation" || value.kind === "project";
13558
+ const root = rootKind(value.kind);
13557
13559
  return root ? value.conversationId === "" : id(value.conversationId);
13558
13560
  }
13561
+ function rootKind(kind) {
13562
+ return kind === "conversation" || kind === "project" || kind === "setting";
13563
+ }
13559
13564
  function embeddings(write) {
13560
13565
  if (write.embeddings === void 0) return true;
13561
13566
  return Array.isArray(write.embeddings) && !write.record.isDeleted && (write.record.kind === "message" || write.record.kind === "summary") && write.embeddings.length <= maxChunksPerRecord && (write.embeddingModel === void 0 || typeof write.embeddingModel === "string" && write.embeddingModel.length <= 256) && Array.from({ length: write.embeddings.length }, (_, i) => i).every(
@@ -13763,7 +13768,7 @@ async function createRemoteChatStore(options) {
13763
13768
  async list(query) {
13764
13769
  const limit = query.limit ?? 20;
13765
13770
  const parent = query.conversationId ?? "";
13766
- if (!kinds.has(query.kind) || !integer(limit, 1) || query.includeDeleted !== void 0 && typeof query.includeDeleted !== "boolean" || limit > 200 || (query.cursor?.length ?? 0) > 2048 || (query.kind === "conversation" || query.kind === "project" ? parent !== "" : !id(parent)))
13771
+ if (!kinds.has(query.kind) || !integer(limit, 1) || query.includeDeleted !== void 0 && typeof query.includeDeleted !== "boolean" || limit > 200 || (query.cursor?.length ?? 0) > 2048 || (rootKind(query.kind) ? parent !== "" : !id(parent)))
13767
13772
  invalid();
13768
13773
  const params = new URLSearchParams({
13769
13774
  account_id: String(accountId),
@@ -13906,10 +13911,12 @@ async function createRemoteChatStore(options) {
13906
13911
  },
13907
13912
  async changes(cursor, options2) {
13908
13913
  const limit = options2?.limit ?? 100;
13909
- if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text5(cursor) || cursor.length > 2048))
13914
+ const kindsFilter = options2?.kinds;
13915
+ if (!integer(limit, 1) || limit > 200 || cursor !== void 0 && (!text5(cursor) || cursor.length > 2048) || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || new Set(kindsFilter).size !== kindsFilter.length || kindsFilter.some((k) => !kinds.has(k))))
13910
13916
  invalid();
13911
13917
  const params = new URLSearchParams({ account_id: String(accountId), limit: String(limit) });
13912
13918
  if (cursor) params.set("cursor", cursor);
13919
+ if (kindsFilter) params.set("kinds", kindsFilter.join(","));
13913
13920
  const value = await request(`/changes?${params}`, {}, options2?.signal);
13914
13921
  if (!object(value) || !Array.isArray(value.items) || value.items.length > limit || value.next_cursor !== void 0 && !text5(value.next_cursor) || value.changes_cursor !== void 0 && !text5(value.changes_cursor))
13915
13922
  invalid();
@@ -14320,6 +14327,62 @@ async function migrateChatsToRemote(options) {
14320
14327
  return passes(false);
14321
14328
  }
14322
14329
 
14330
+ // src/lib/chatStore/settings.ts
14331
+ var maxSaveAttempts = 3;
14332
+ function toSetting(snapshot) {
14333
+ if (snapshot.record.isDeleted) return null;
14334
+ return {
14335
+ section: snapshot.record.id,
14336
+ data: snapshot.record.data,
14337
+ version: snapshot.version,
14338
+ createdAt: snapshot.record.createdAt,
14339
+ updatedAt: snapshot.record.updatedAt
14340
+ };
14341
+ }
14342
+ async function loadSettings(store, signal) {
14343
+ const out = /* @__PURE__ */ new Map();
14344
+ let cursor;
14345
+ do {
14346
+ const page = await store.list({ kind: "setting", limit: 100, cursor, signal });
14347
+ for (const item of page.items) {
14348
+ const setting = toSetting(item);
14349
+ if (setting) out.set(setting.section, setting);
14350
+ }
14351
+ cursor = page.nextCursor;
14352
+ } while (cursor);
14353
+ return out;
14354
+ }
14355
+ async function saveSetting(store, section, data, signal) {
14356
+ for (let attempt = 1; ; attempt++) {
14357
+ const current = await store.get("setting", section, signal);
14358
+ const now = Date.now();
14359
+ try {
14360
+ const [saved] = await store.putMany(
14361
+ [
14362
+ {
14363
+ record: {
14364
+ kind: "setting",
14365
+ id: section,
14366
+ conversationId: "",
14367
+ sortKey: 0,
14368
+ createdAt: current?.record.createdAt ?? now,
14369
+ updatedAt: Math.max(now, (current?.record.updatedAt ?? 0) + 1),
14370
+ isDeleted: false,
14371
+ data
14372
+ },
14373
+ expectedVersion: current?.version ?? 0
14374
+ }
14375
+ ],
14376
+ signal
14377
+ );
14378
+ return toSetting(saved);
14379
+ } catch (error) {
14380
+ if (!(error instanceof ChatStoreError) || error.code !== "version_conflict" || attempt >= maxSaveAttempts)
14381
+ throw error;
14382
+ }
14383
+ }
14384
+ }
14385
+
14323
14386
  // src/lib/chatStore/vaultAttachments.ts
14324
14387
  var frameVersion = 1;
14325
14388
  var ivBytes = 12;
@@ -21528,6 +21591,7 @@ init_logger();
21528
21591
  init_redactor();
21529
21592
 
21530
21593
  // src/lib/memory/entitySalience.ts
21594
+ init_patterns();
21531
21595
  var GENERIC_ENTITY_NAMES = /* @__PURE__ */ new Set([
21532
21596
  "today",
21533
21597
  "tomorrow",
@@ -21673,6 +21737,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
21673
21737
  "and",
21674
21738
  "or"
21675
21739
  ]);
21740
+ var MAX_ENTITY_NAME_LENGTH = 120;
21741
+ var MAX_ENTITY_NAME_TOKENS = 11;
21742
+ var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
21743
+ var BARE_HEX = /^[0-9a-f]{32,}$/i;
21744
+ var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
21745
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
21746
+ var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
21747
+ var KEY_SEGMENT_MIN_LENGTH = 16;
21748
+ var LONG_DIGIT_RUN = /^\d{6,}$/;
21749
+ var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
21750
+ var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
21751
+ var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
21752
+ var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
21753
+ var BARE_INTEGER = /^\d+$/;
21754
+ var TICKER = /^\$?[A-Z]{2,6}$/;
21755
+ var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
21756
+ var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
21757
+ var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
21758
+ var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
21759
+ var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
21760
+ "usd",
21761
+ "usdc",
21762
+ "usdt",
21763
+ "eur",
21764
+ "gbp",
21765
+ "sol",
21766
+ "eth",
21767
+ "btc",
21768
+ "dollar",
21769
+ "dollars",
21770
+ "euro",
21771
+ "euros",
21772
+ "buck",
21773
+ "bucks",
21774
+ "k",
21775
+ "thousand",
21776
+ "million",
21777
+ "billion",
21778
+ "trillion",
21779
+ "share",
21780
+ "shares",
21781
+ "token",
21782
+ "tokens",
21783
+ "coin",
21784
+ "coins",
21785
+ "unit",
21786
+ "units",
21787
+ "position",
21788
+ "balance",
21789
+ "stake",
21790
+ "holdings"
21791
+ ]);
21792
+ var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
21793
+ var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
21794
+ var NAME_PII_PATTERNS = PII_PATTERNS.filter(
21795
+ (pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
21796
+ );
21797
+ var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
21798
+ var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
21799
+ function trimPunctuation(token) {
21800
+ const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
21801
+ let end = chars.length;
21802
+ while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
21803
+ return chars.slice(0, end).join("");
21804
+ }
21805
+ function hasLetterAndDigit(text16) {
21806
+ return /\p{L}/u.test(text16) && /\p{N}/u.test(text16);
21807
+ }
21808
+ function isIdentifierToken(token) {
21809
+ if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
21810
+ if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
21811
+ if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
21812
+ return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
21813
+ }
21814
+ function containsStructuredPii(name) {
21815
+ return NAME_PII_PATTERNS.some(
21816
+ (pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
21817
+ );
21818
+ }
21819
+ function isAmountUnitToken(token) {
21820
+ return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
21821
+ }
21822
+ function isAmountWordOrNumber(token) {
21823
+ return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
21824
+ }
21825
+ function isAmount(tokens) {
21826
+ const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
21827
+ const first = tokens[start];
21828
+ if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
21829
+ const units = tokens.slice(start + 1);
21830
+ if (start === 0 && units.length === 0)
21831
+ return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
21832
+ if (!units.every(isAmountUnitToken)) return false;
21833
+ return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
21834
+ }
21835
+ function hasQuantityPhrase(tokens) {
21836
+ return tokens.some(
21837
+ (token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
21838
+ );
21839
+ }
21840
+ function isIdentifierOrAmountEntityName(name) {
21841
+ const trimmed = name.trim();
21842
+ if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
21843
+ if (containsStructuredPii(trimmed)) return true;
21844
+ const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
21845
+ if (tokens.length === 0) return false;
21846
+ if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
21847
+ if (tokens.some(isIdentifierToken)) return true;
21848
+ if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
21849
+ return isAmount(tokens) || hasQuantityPhrase(tokens);
21850
+ }
21851
+ function restoreEntityName(name, redactor) {
21852
+ for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
21853
+ if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
21854
+ if (redactor.restoreForStorage(token).text !== token) return null;
21855
+ }
21856
+ const restored = redactor.restoreForStorage(name);
21857
+ return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
21858
+ }
21676
21859
 
21677
21860
  // src/lib/memory/injectionClassifier.ts
21678
21861
  init_logger();
@@ -24485,8 +24668,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
24485
24668
  ...c,
24486
24669
  content: content.text,
24487
24670
  entities: c.entities.flatMap((e) => {
24488
- const restored = redactor.restoreForStorage(e.name);
24489
- return restored.unresolved ? [] : [{ ...e, name: restored.text }];
24671
+ const name = restoreEntityName(e.name, redactor);
24672
+ return name === null ? [] : [{ ...e, name }];
24490
24673
  })
24491
24674
  },
24492
24675
  unresolved: content.unresolved
@@ -24754,18 +24937,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
24754
24937
  }
24755
24938
  return out;
24756
24939
  }
24940
+ function isAcceptedEntityName(name) {
24941
+ return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
24942
+ }
24757
24943
  function parseEntities(raw) {
24758
24944
  const out = [];
24759
24945
  for (const e of raw) {
24760
24946
  if (typeof e === "string") {
24761
24947
  const name2 = e.trim();
24762
- if (name2.length > 0 && !isGenericEntityName(name2)) out.push({ name: name2 });
24948
+ if (isAcceptedEntityName(name2)) out.push({ name: name2 });
24763
24949
  continue;
24764
24950
  }
24765
24951
  if (typeof e !== "object" || e === null) continue;
24766
24952
  const obj = e;
24767
24953
  const name = typeof obj.name === "string" ? obj.name.trim() : "";
24768
- if (name.length === 0 || isGenericEntityName(name)) continue;
24954
+ if (!isAcceptedEntityName(name)) continue;
24769
24955
  const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
24770
24956
  const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
24771
24957
  out.push({
@@ -26955,6 +27141,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
26955
27141
  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:
26956
27142
  - 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.
26957
27143
  - KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
27144
+ - SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
26958
27145
  - Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
26959
27146
  ${ENTITY_KIND_GUIDELINES}
26960
27147
 
@@ -27060,8 +27247,8 @@ List each memory's named entities.`,
27060
27247
  }
27061
27248
  function restoreEntities(entities, redactor) {
27062
27249
  return entities.flatMap((e) => {
27063
- const restored = redactor.restoreForStorage(e.name);
27064
- return restored.unresolved ? [] : [{ ...e, name: restored.text }];
27250
+ const name = restoreEntityName(e.name, redactor);
27251
+ return name === null ? [] : [{ ...e, name }];
27065
27252
  });
27066
27253
  }
27067
27254
  function parseTopicResponse(parsed, validIds) {
@@ -39438,6 +39625,7 @@ function useCredits(options = {}) {
39438
39625
  const baseUrlRef = (0, import_react8.useRef)(baseUrl);
39439
39626
  const onErrorRef = (0, import_react8.useRef)(onError);
39440
39627
  const abortControllerRef = (0, import_react8.useRef)(null);
39628
+ const hasFetchedRef = (0, import_react8.useRef)(false);
39441
39629
  (0, import_react8.useEffect)(() => {
39442
39630
  getTokenRef.current = getToken;
39443
39631
  baseUrlRef.current = baseUrl;
@@ -39445,6 +39633,7 @@ function useCredits(options = {}) {
39445
39633
  });
39446
39634
  (0, import_react8.useEffect)(() => {
39447
39635
  return () => {
39636
+ hasFetchedRef.current = false;
39448
39637
  if (abortControllerRef.current) {
39449
39638
  abortControllerRef.current.abort();
39450
39639
  abortControllerRef.current = null;
@@ -39492,14 +39681,14 @@ function useCredits(options = {}) {
39492
39681
  headers,
39493
39682
  signal
39494
39683
  });
39684
+ if (signal.aborted) return;
39495
39685
  if (response.error) {
39496
39686
  const errorMsg = response.error.error ?? "Failed to fetch credit balance";
39497
- throw new Error(errorMsg);
39687
+ throw Object.assign(new Error(errorMsg), { cause: response.error });
39498
39688
  }
39499
- if (signal.aborted) return;
39500
39689
  setBalance(response.data ?? null);
39501
39690
  } catch (err) {
39502
- if (err instanceof Error && err.name === "AbortError") return;
39691
+ if (signal.aborted || err instanceof Error && err.name === "AbortError") return;
39503
39692
  handleError(err);
39504
39693
  } finally {
39505
39694
  stopLoading();
@@ -39561,7 +39750,6 @@ function useCredits(options = {}) {
39561
39750
  },
39562
39751
  [getHeaders, handleError, startLoading, stopLoading]
39563
39752
  );
39564
- const hasFetchedRef = (0, import_react8.useRef)(false);
39565
39753
  (0, import_react8.useEffect)(() => {
39566
39754
  if (autoFetch && !hasFetchedRef.current) {
39567
39755
  hasFetchedRef.current = true;
@@ -41491,6 +41679,8 @@ function useSubscription(options = {}) {
41491
41679
  const baseUrlRef = (0, import_react20.useRef)(baseUrl);
41492
41680
  const onErrorRef = (0, import_react20.useRef)(onError);
41493
41681
  const abortControllerRef = (0, import_react20.useRef)(null);
41682
+ const hasFetchedRef = (0, import_react20.useRef)(false);
41683
+ const loadingCountRef = (0, import_react20.useRef)(0);
41494
41684
  (0, import_react20.useEffect)(() => {
41495
41685
  getTokenRef.current = getToken;
41496
41686
  baseUrlRef.current = baseUrl;
@@ -41498,12 +41688,21 @@ function useSubscription(options = {}) {
41498
41688
  });
41499
41689
  (0, import_react20.useEffect)(() => {
41500
41690
  return () => {
41691
+ hasFetchedRef.current = false;
41501
41692
  if (abortControllerRef.current) {
41502
41693
  abortControllerRef.current.abort();
41503
41694
  abortControllerRef.current = null;
41504
41695
  }
41505
41696
  };
41506
41697
  }, []);
41698
+ const startLoading = (0, import_react20.useCallback)(() => {
41699
+ loadingCountRef.current++;
41700
+ setIsLoading(true);
41701
+ }, []);
41702
+ const stopLoading = (0, import_react20.useCallback)(() => {
41703
+ loadingCountRef.current = Math.max(0, loadingCountRef.current - 1);
41704
+ setIsLoading(loadingCountRef.current > 0);
41705
+ }, []);
41507
41706
  const getHeaders = (0, import_react20.useCallback)(async () => {
41508
41707
  const headers = {};
41509
41708
  if (getTokenRef.current) {
@@ -41527,7 +41726,7 @@ function useSubscription(options = {}) {
41527
41726
  const abortController = new AbortController();
41528
41727
  abortControllerRef.current = abortController;
41529
41728
  const signal = abortController.signal;
41530
- setIsLoading(true);
41729
+ startLoading();
41531
41730
  setError(null);
41532
41731
  try {
41533
41732
  const headers = await getHeaders();
@@ -41537,33 +41736,31 @@ function useSubscription(options = {}) {
41537
41736
  headers,
41538
41737
  signal
41539
41738
  });
41739
+ if (signal.aborted) return;
41540
41740
  if (response.error) {
41541
41741
  const errorMsg = response.error.error ?? "Failed to fetch subscription status";
41542
- throw new Error(errorMsg);
41742
+ throw Object.assign(new Error(errorMsg), { cause: response.error });
41543
41743
  }
41544
- if (signal.aborted) return;
41545
41744
  setStatus(response.data ?? null);
41546
41745
  } catch (err) {
41547
- if (err instanceof Error && err.name === "AbortError") {
41746
+ if (signal.aborted || err instanceof Error && err.name === "AbortError") {
41548
41747
  return;
41549
41748
  }
41550
41749
  handleError(err);
41551
41750
  } finally {
41552
- if (!signal.aborted) {
41553
- setIsLoading(false);
41554
- }
41751
+ stopLoading();
41555
41752
  if (abortControllerRef.current === abortController) {
41556
41753
  abortControllerRef.current = null;
41557
41754
  }
41558
41755
  }
41559
- }, [getHeaders, handleError]);
41756
+ }, [getHeaders, handleError, startLoading, stopLoading]);
41560
41757
  const refetch = (0, import_react20.useCallback)(async () => {
41561
41758
  setStatus(null);
41562
41759
  await fetchStatus();
41563
41760
  }, [fetchStatus]);
41564
41761
  const createCheckoutSession = (0, import_react20.useCallback)(
41565
41762
  async (opts) => {
41566
- setIsLoading(true);
41763
+ startLoading();
41567
41764
  setError(null);
41568
41765
  try {
41569
41766
  const headers = await getHeaders();
@@ -41586,14 +41783,14 @@ function useSubscription(options = {}) {
41586
41783
  handleError(err);
41587
41784
  return null;
41588
41785
  } finally {
41589
- setIsLoading(false);
41786
+ stopLoading();
41590
41787
  }
41591
41788
  },
41592
- [getHeaders, handleError]
41789
+ [getHeaders, handleError, startLoading, stopLoading]
41593
41790
  );
41594
41791
  const openCustomerPortal = (0, import_react20.useCallback)(
41595
41792
  async (opts) => {
41596
- setIsLoading(true);
41793
+ startLoading();
41597
41794
  setError(null);
41598
41795
  try {
41599
41796
  const headers = await getHeaders();
@@ -41613,13 +41810,13 @@ function useSubscription(options = {}) {
41613
41810
  handleError(err);
41614
41811
  return null;
41615
41812
  } finally {
41616
- setIsLoading(false);
41813
+ stopLoading();
41617
41814
  }
41618
41815
  },
41619
- [getHeaders, handleError]
41816
+ [getHeaders, handleError, startLoading, stopLoading]
41620
41817
  );
41621
41818
  const cancelSubscription = (0, import_react20.useCallback)(async () => {
41622
- setIsLoading(true);
41819
+ startLoading();
41623
41820
  setError(null);
41624
41821
  try {
41625
41822
  const headers = await getHeaders();
@@ -41637,11 +41834,11 @@ function useSubscription(options = {}) {
41637
41834
  handleError(err);
41638
41835
  return null;
41639
41836
  } finally {
41640
- setIsLoading(false);
41837
+ stopLoading();
41641
41838
  }
41642
- }, [getHeaders, handleError, fetchStatus]);
41839
+ }, [getHeaders, handleError, startLoading, stopLoading, fetchStatus]);
41643
41840
  const renewSubscription = (0, import_react20.useCallback)(async () => {
41644
- setIsLoading(true);
41841
+ startLoading();
41645
41842
  setError(null);
41646
41843
  try {
41647
41844
  const headers = await getHeaders();
@@ -41659,10 +41856,9 @@ function useSubscription(options = {}) {
41659
41856
  handleError(err);
41660
41857
  return null;
41661
41858
  } finally {
41662
- setIsLoading(false);
41859
+ stopLoading();
41663
41860
  }
41664
- }, [getHeaders, handleError, fetchStatus]);
41665
- const hasFetchedRef = (0, import_react20.useRef)(false);
41861
+ }, [getHeaders, handleError, startLoading, stopLoading, fetchStatus]);
41666
41862
  (0, import_react20.useEffect)(() => {
41667
41863
  if (autoFetch && !hasFetchedRef.current) {
41668
41864
  hasFetchedRef.current = true;
@@ -42220,6 +42416,8 @@ function useWalletBinding(options = {}) {
42220
42416
  const baseUrlRef = (0, import_react24.useRef)(baseUrl);
42221
42417
  const onErrorRef = (0, import_react24.useRef)(onError);
42222
42418
  const abortControllerRef = (0, import_react24.useRef)(null);
42419
+ const hasFetchedRef = (0, import_react24.useRef)(false);
42420
+ const loadingCountRef = (0, import_react24.useRef)(0);
42223
42421
  (0, import_react24.useEffect)(() => {
42224
42422
  getTokenRef.current = getToken;
42225
42423
  baseUrlRef.current = baseUrl;
@@ -42227,12 +42425,21 @@ function useWalletBinding(options = {}) {
42227
42425
  });
42228
42426
  (0, import_react24.useEffect)(() => {
42229
42427
  return () => {
42428
+ hasFetchedRef.current = false;
42230
42429
  if (abortControllerRef.current) {
42231
42430
  abortControllerRef.current.abort();
42232
42431
  abortControllerRef.current = null;
42233
42432
  }
42234
42433
  };
42235
42434
  }, []);
42435
+ const startLoading = (0, import_react24.useCallback)(() => {
42436
+ loadingCountRef.current++;
42437
+ setIsLoading(true);
42438
+ }, []);
42439
+ const stopLoading = (0, import_react24.useCallback)(() => {
42440
+ loadingCountRef.current = Math.max(0, loadingCountRef.current - 1);
42441
+ setIsLoading(loadingCountRef.current > 0);
42442
+ }, []);
42236
42443
  const getHeaders = (0, import_react24.useCallback)(async () => {
42237
42444
  const headers = {};
42238
42445
  if (getTokenRef.current) {
@@ -42256,7 +42463,7 @@ function useWalletBinding(options = {}) {
42256
42463
  const abortController = new AbortController();
42257
42464
  abortControllerRef.current = abortController;
42258
42465
  const signal = abortController.signal;
42259
- setIsLoading(true);
42466
+ startLoading();
42260
42467
  setError(null);
42261
42468
  try {
42262
42469
  const headers = await getHeaders();
@@ -42266,34 +42473,32 @@ function useWalletBinding(options = {}) {
42266
42473
  headers,
42267
42474
  signal
42268
42475
  });
42476
+ if (signal.aborted) return;
42269
42477
  if (response.error) {
42270
42478
  const errorMsg = response.error.error ?? "Failed to fetch bound wallets";
42271
- throw new Error(errorMsg);
42479
+ throw Object.assign(new Error(errorMsg), { cause: response.error });
42272
42480
  }
42273
- if (signal.aborted) return;
42274
42481
  setWallets(response.data?.wallets ?? []);
42275
42482
  setTotals(response.data?.totals ?? null);
42276
42483
  } catch (err) {
42277
- if (err instanceof Error && err.name === "AbortError") {
42484
+ if (signal.aborted || err instanceof Error && err.name === "AbortError") {
42278
42485
  return;
42279
42486
  }
42280
42487
  handleError(err);
42281
42488
  } finally {
42282
- if (!signal.aborted) {
42283
- setIsLoading(false);
42284
- }
42489
+ stopLoading();
42285
42490
  if (abortControllerRef.current === abortController) {
42286
42491
  abortControllerRef.current = null;
42287
42492
  }
42288
42493
  }
42289
- }, [getHeaders, handleError]);
42494
+ }, [getHeaders, handleError, startLoading, stopLoading]);
42290
42495
  const refetch = (0, import_react24.useCallback)(async () => {
42291
42496
  setWallets([]);
42292
42497
  setTotals(null);
42293
42498
  await fetchBinding();
42294
42499
  }, [fetchBinding]);
42295
42500
  const getNonce = (0, import_react24.useCallback)(async () => {
42296
- setIsLoading(true);
42501
+ startLoading();
42297
42502
  setError(null);
42298
42503
  try {
42299
42504
  const headers = await getHeaders();
@@ -42310,12 +42515,12 @@ function useWalletBinding(options = {}) {
42310
42515
  handleError(err);
42311
42516
  return null;
42312
42517
  } finally {
42313
- setIsLoading(false);
42518
+ stopLoading();
42314
42519
  }
42315
- }, [getHeaders, handleError]);
42520
+ }, [getHeaders, handleError, startLoading, stopLoading]);
42316
42521
  const bindWallet = (0, import_react24.useCallback)(
42317
42522
  async (request) => {
42318
- setIsLoading(true);
42523
+ startLoading();
42319
42524
  setError(null);
42320
42525
  try {
42321
42526
  const headers = await getHeaders();
@@ -42334,14 +42539,14 @@ function useWalletBinding(options = {}) {
42334
42539
  handleError(err);
42335
42540
  return null;
42336
42541
  } finally {
42337
- setIsLoading(false);
42542
+ stopLoading();
42338
42543
  }
42339
42544
  },
42340
- [getHeaders, handleError, fetchBinding]
42545
+ [getHeaders, handleError, startLoading, stopLoading, fetchBinding]
42341
42546
  );
42342
42547
  const unbindWallet = (0, import_react24.useCallback)(
42343
42548
  async (address) => {
42344
- setIsLoading(true);
42549
+ startLoading();
42345
42550
  setError(null);
42346
42551
  try {
42347
42552
  const headers = await getHeaders();
@@ -42360,12 +42565,11 @@ function useWalletBinding(options = {}) {
42360
42565
  handleError(err);
42361
42566
  return false;
42362
42567
  } finally {
42363
- setIsLoading(false);
42568
+ stopLoading();
42364
42569
  }
42365
42570
  },
42366
- [getHeaders, handleError, fetchBinding]
42571
+ [getHeaders, handleError, startLoading, stopLoading, fetchBinding]
42367
42572
  );
42368
- const hasFetchedRef = (0, import_react24.useRef)(false);
42369
42573
  (0, import_react24.useEffect)(() => {
42370
42574
  if (autoFetch && !hasFetchedRef.current) {
42371
42575
  hasFetchedRef.current = true;
@@ -42706,6 +42910,7 @@ function useWalletBinding(options = {}) {
42706
42910
  isSupportedFile,
42707
42911
  isSupportedMediaType,
42708
42912
  linkMemoryEntitiesOp,
42913
+ loadSettings,
42709
42914
  localChatBackend,
42710
42915
  maskScopedEmbeddingCache,
42711
42916
  maxVaultAttachmentBytes,
@@ -42753,6 +42958,7 @@ function useWalletBinding(options = {}) {
42753
42958
  resumeStream,
42754
42959
  retain,
42755
42960
  revokeNotionAccess,
42961
+ saveSetting,
42756
42962
  savedToolToStored,
42757
42963
  scoreProfileSalience,
42758
42964
  screenCandidatesForInjection,