@anuma/sdk 3.0.0 → 3.1.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.
@@ -2741,6 +2741,33 @@ interface CachedServerTools {
2741
2741
  /** Checksum from the server for cache invalidation */
2742
2742
  checksum?: string;
2743
2743
  }
2744
+ /**
2745
+ * Pluggable persistence for the fetched server-tools list.
2746
+ *
2747
+ * The default backend ({@link localStorageToolsCache}) writes to browser
2748
+ * `localStorage` and is a silent no-op where `localStorage` is undefined
2749
+ * (Node, React Native). Pass a custom backend to `getServerTools` to cache
2750
+ * somewhere that survives on those platforms — e.g. an AsyncStorage/MMKV
2751
+ * adapter on RN, or an in-memory `Map` on a server. Methods may be sync or
2752
+ * async; `getServerTools` awaits them either way.
2753
+ *
2754
+ * The stored payload carries a `version`; `getServerTools` discards any entry
2755
+ * whose version does not match the current cache format, so a stale custom
2756
+ * backend can never feed an incompatible shape back into selection.
2757
+ */
2758
+ interface ToolsCacheBackend {
2759
+ /** Return the cached payload, or null when absent/unreadable. */
2760
+ get(): CachedServerTools | null | Promise<CachedServerTools | null>;
2761
+ /** Persist the payload. Implementations should swallow write failures. */
2762
+ set(value: CachedServerTools): void | Promise<void>;
2763
+ /**
2764
+ * Remove the cached payload. Optional — a read/write-only backend may omit it,
2765
+ * in which case `clearServerToolsCache` (and the version-mismatch
2766
+ * invalidation) is a no-op for that backend. The default
2767
+ * {@link localStorageToolsCache} implements it.
2768
+ */
2769
+ clear?(): void | Promise<void>;
2770
+ }
2744
2771
  /**
2745
2772
  * Options for fetching server tools
2746
2773
  */
@@ -2755,6 +2782,12 @@ interface ServerToolsOptions {
2755
2782
  getToken?: () => Promise<string | null>;
2756
2783
  /** Direct API key for server-side usage (uses X-API-Key header) */
2757
2784
  apiKey?: string;
2785
+ /**
2786
+ * Where to read/write the cached tools list. Defaults to
2787
+ * {@link localStorageToolsCache} (browser `localStorage`; no-op elsewhere).
2788
+ * Provide a backend to enable caching on Node / React Native.
2789
+ */
2790
+ cache?: ToolsCacheBackend;
2758
2791
  }
2759
2792
  /** Default cache expiration: 1 day */
2760
2793
  declare const DEFAULT_CACHE_EXPIRATION_MS: number;
@@ -2770,14 +2803,21 @@ interface ParsedServerToolsResponse {
2770
2803
  */
2771
2804
  declare function getCachedServerTools(): CachedServerTools | null;
2772
2805
  /**
2773
- * Clear the server tools cache
2806
+ * Clear the cached server tools. Defaults to the browser-`localStorage` backend;
2807
+ * pass the SAME {@link ToolsCacheBackend} you gave `getServerTools` to invalidate
2808
+ * a custom backend (a no-op when that backend defines no `clear`). Returns the
2809
+ * backend's clear result, which may be async.
2774
2810
  */
2775
2811
  declare function clearServerToolsCache(): void;
2812
+ declare function clearServerToolsCache(cache: ToolsCacheBackend): void | Promise<void>;
2776
2813
  /**
2777
- * Get the checksum of currently cached tools.
2778
- * Returns undefined if no cache or no checksum stored.
2814
+ * Get the checksum of the currently cached tools, or undefined when there is no
2815
+ * cache / no stored checksum. Defaults to the browser-`localStorage` backend;
2816
+ * pass the SAME backend you gave `getServerTools` to read a custom backend's
2817
+ * checksum (an async backend yields a promise).
2779
2818
  */
2780
2819
  declare function getToolsChecksum(): string | undefined;
2820
+ declare function getToolsChecksum(cache: ToolsCacheBackend): string | undefined | Promise<string | undefined>;
2781
2821
  /**
2782
2822
  * Check if tools should be refreshed based on checksum comparison.
2783
2823
  * Returns true if:
@@ -2789,11 +2829,12 @@ declare function getToolsChecksum(): string | undefined;
2789
2829
  * - Checksums match
2790
2830
  */
2791
2831
  declare function shouldRefreshTools(responseChecksum: string | undefined): boolean;
2832
+ declare function shouldRefreshTools(responseChecksum: string | undefined, cache: ToolsCacheBackend | undefined): boolean | Promise<boolean>;
2792
2833
  /**
2793
2834
  * Get server tools with caching support.
2794
2835
  *
2795
2836
  * Flow:
2796
- * 1. Check localStorage cache
2837
+ * 1. Check the cache backend (localStorage by default; override via `cache`)
2797
2838
  * 2. If cache valid and not force refresh, return cached tools
2798
2839
  * 3. Otherwise, fetch from API, cache, and return
2799
2840
  * 4. On fetch failure, return cached tools if available (stale-while-error)
@@ -3085,6 +3126,11 @@ interface SelectServerToolsForPromptOptions {
3085
3126
  embeddingModel?: string;
3086
3127
  /** Cache expiration in ms for the server-tools catalog fetch. */
3087
3128
  cacheExpirationMs?: number;
3129
+ /**
3130
+ * Where to read/write the cached catalog. Defaults to browser `localStorage`
3131
+ * (a no-op on Node/RN); pass a backend to persist on those platforms.
3132
+ */
3133
+ cache?: ToolsCacheBackend;
3088
3134
  /**
3089
3135
  * Phase 3 defer-loading. When `enabled`, this helper returns the FULL catalog (skipping semantic/
3090
3136
  * static filtering) to mirror useChatStorage's responses send path, which swaps in the full catalog
@@ -5366,11 +5412,26 @@ interface EmbeddingOptions {
5366
5412
  }
5367
5413
 
5368
5414
  /**
5369
- * Memory Retrieval Embeddings
5415
+ * Embedding generation — dependency-free core.
5416
+ *
5417
+ * The raw "text → embedding" calls, split out of `embeddings.ts` so they can be
5418
+ * imported by node/React-Native-safe modules (the server-tool + client-tool
5419
+ * selection engine in `../tools`) WITHOUT pulling in the WatermelonDB-backed
5420
+ * `db/chat/operations` that `embeddings.ts` needs for its message-persistence
5421
+ * helpers (`embedMessage`, `embedAllMessages`, `chunkAndEmbed*`).
5370
5422
  *
5371
- * Functions for generating and storing embeddings for conversation messages.
5423
+ * Nothing here touches the database; the only I/O is the HTTP embeddings
5424
+ * endpoint. `embeddings.ts` re-exports these so existing importers of
5425
+ * `../memoryEngine/embeddings` (and the `../memoryEngine` barrel) keep working.
5372
5426
  */
5373
5427
 
5428
+ /**
5429
+ * Generate an embedding for text using the API
5430
+ *
5431
+ * Supports two auth methods:
5432
+ * - `apiKey`: Uses X-API-Key header (for server-side/CLI usage)
5433
+ * - `getToken`: Uses Authorization: Bearer header (for Privy identity tokens)
5434
+ */
5374
5435
  declare function generateEmbedding(text: string, options: EmbeddingOptions): Promise<number[]>;
5375
5436
  /**
5376
5437
  * Generate embeddings for multiple texts, automatically chunking large inputs.
@@ -5385,6 +5446,18 @@ declare function generateEmbedding(text: string, options: EmbeddingOptions): Pro
5385
5446
  * @returns Array of embeddings in the same order as input texts
5386
5447
  */
5387
5448
  declare function generateEmbeddings(texts: string[], options: EmbeddingOptions): Promise<number[][]>;
5449
+
5450
+ /**
5451
+ * Memory Retrieval Embeddings
5452
+ *
5453
+ * Message-level embedding + persistence helpers: find messages via the
5454
+ * WatermelonDB-backed `db/chat/operations`, embed their content, and store the
5455
+ * vectors/chunks back. The raw "text → embedding" calls live in `./generate`
5456
+ * (dependency-free so the tool-selection engine can import them without the DB
5457
+ * layer) and are re-exported here so existing importers of
5458
+ * `../memoryEngine/embeddings` and the `../memoryEngine` barrel keep working.
5459
+ */
5460
+
5388
5461
  /**
5389
5462
  * Embed a single message and store the embedding in the database
5390
5463
  *
@@ -6583,14 +6656,14 @@ declare function createChunkVectorCache(maxSize?: number): ChunkVectorCache;
6583
6656
  declare function recall(query: string, ctx: RecallContext, options?: RecallOptions): Promise<RecallResult>;
6584
6657
 
6585
6658
  /**
6586
- * Unified Recall Tool
6659
+ * Recall tool constants — deliberately dependency-free.
6587
6660
  *
6588
- * Single chat-completion tool that searches both vault facts and
6589
- * conversation chunks via `recall()`. Replaces the legacy pair of
6590
- * `memory_vault_search` (facts) + `search_memory` (chunks) — the LLM no
6591
- * longer has to route between two tools.
6661
+ * Split out of `recallTool.ts` so the tool NAME can be referenced from
6662
+ * node/React-Native-safe modules (e.g. the client-tool selector in
6663
+ * `../tools/clientToolSelection`) without dragging `recall()` and its
6664
+ * WatermelonDB-backed operations into the module graph. `recallTool.ts`
6665
+ * re-exports these to preserve their public identity.
6592
6666
  */
6593
-
6594
6667
  /** Tool name surfaced to the LLM. Exported so bench harnesses and chat
6595
6668
  * clients reference the same string — drift between prod and bench would
6596
6669
  * mask tool-routing bugs in eval. */
@@ -6598,6 +6671,16 @@ declare const RECALL_TOOL_NAME = "recall_memory";
6598
6671
  /** Maximum results the executor will return to the LLM, regardless of
6599
6672
  * the LLM-supplied `limit`. */
6600
6673
  declare const RECALL_MAX_LIMIT = 50;
6674
+
6675
+ /**
6676
+ * Unified Recall Tool
6677
+ *
6678
+ * Single chat-completion tool that searches both vault facts and
6679
+ * conversation chunks via `recall()`. Replaces the legacy pair of
6680
+ * `memory_vault_search` (facts) + `search_memory` (chunks) — the LLM no
6681
+ * longer has to route between two tools.
6682
+ */
6683
+
6601
6684
  interface RecallToolOptions {
6602
6685
  /** Lanes to search. Default: ["fact", "chunk"]. */
6603
6686
  types?: MemoryKind[];
@@ -2741,6 +2741,33 @@ interface CachedServerTools {
2741
2741
  /** Checksum from the server for cache invalidation */
2742
2742
  checksum?: string;
2743
2743
  }
2744
+ /**
2745
+ * Pluggable persistence for the fetched server-tools list.
2746
+ *
2747
+ * The default backend ({@link localStorageToolsCache}) writes to browser
2748
+ * `localStorage` and is a silent no-op where `localStorage` is undefined
2749
+ * (Node, React Native). Pass a custom backend to `getServerTools` to cache
2750
+ * somewhere that survives on those platforms — e.g. an AsyncStorage/MMKV
2751
+ * adapter on RN, or an in-memory `Map` on a server. Methods may be sync or
2752
+ * async; `getServerTools` awaits them either way.
2753
+ *
2754
+ * The stored payload carries a `version`; `getServerTools` discards any entry
2755
+ * whose version does not match the current cache format, so a stale custom
2756
+ * backend can never feed an incompatible shape back into selection.
2757
+ */
2758
+ interface ToolsCacheBackend {
2759
+ /** Return the cached payload, or null when absent/unreadable. */
2760
+ get(): CachedServerTools | null | Promise<CachedServerTools | null>;
2761
+ /** Persist the payload. Implementations should swallow write failures. */
2762
+ set(value: CachedServerTools): void | Promise<void>;
2763
+ /**
2764
+ * Remove the cached payload. Optional — a read/write-only backend may omit it,
2765
+ * in which case `clearServerToolsCache` (and the version-mismatch
2766
+ * invalidation) is a no-op for that backend. The default
2767
+ * {@link localStorageToolsCache} implements it.
2768
+ */
2769
+ clear?(): void | Promise<void>;
2770
+ }
2744
2771
  /**
2745
2772
  * Options for fetching server tools
2746
2773
  */
@@ -2755,6 +2782,12 @@ interface ServerToolsOptions {
2755
2782
  getToken?: () => Promise<string | null>;
2756
2783
  /** Direct API key for server-side usage (uses X-API-Key header) */
2757
2784
  apiKey?: string;
2785
+ /**
2786
+ * Where to read/write the cached tools list. Defaults to
2787
+ * {@link localStorageToolsCache} (browser `localStorage`; no-op elsewhere).
2788
+ * Provide a backend to enable caching on Node / React Native.
2789
+ */
2790
+ cache?: ToolsCacheBackend;
2758
2791
  }
2759
2792
  /** Default cache expiration: 1 day */
2760
2793
  declare const DEFAULT_CACHE_EXPIRATION_MS: number;
@@ -2770,14 +2803,21 @@ interface ParsedServerToolsResponse {
2770
2803
  */
2771
2804
  declare function getCachedServerTools(): CachedServerTools | null;
2772
2805
  /**
2773
- * Clear the server tools cache
2806
+ * Clear the cached server tools. Defaults to the browser-`localStorage` backend;
2807
+ * pass the SAME {@link ToolsCacheBackend} you gave `getServerTools` to invalidate
2808
+ * a custom backend (a no-op when that backend defines no `clear`). Returns the
2809
+ * backend's clear result, which may be async.
2774
2810
  */
2775
2811
  declare function clearServerToolsCache(): void;
2812
+ declare function clearServerToolsCache(cache: ToolsCacheBackend): void | Promise<void>;
2776
2813
  /**
2777
- * Get the checksum of currently cached tools.
2778
- * Returns undefined if no cache or no checksum stored.
2814
+ * Get the checksum of the currently cached tools, or undefined when there is no
2815
+ * cache / no stored checksum. Defaults to the browser-`localStorage` backend;
2816
+ * pass the SAME backend you gave `getServerTools` to read a custom backend's
2817
+ * checksum (an async backend yields a promise).
2779
2818
  */
2780
2819
  declare function getToolsChecksum(): string | undefined;
2820
+ declare function getToolsChecksum(cache: ToolsCacheBackend): string | undefined | Promise<string | undefined>;
2781
2821
  /**
2782
2822
  * Check if tools should be refreshed based on checksum comparison.
2783
2823
  * Returns true if:
@@ -2789,11 +2829,12 @@ declare function getToolsChecksum(): string | undefined;
2789
2829
  * - Checksums match
2790
2830
  */
2791
2831
  declare function shouldRefreshTools(responseChecksum: string | undefined): boolean;
2832
+ declare function shouldRefreshTools(responseChecksum: string | undefined, cache: ToolsCacheBackend | undefined): boolean | Promise<boolean>;
2792
2833
  /**
2793
2834
  * Get server tools with caching support.
2794
2835
  *
2795
2836
  * Flow:
2796
- * 1. Check localStorage cache
2837
+ * 1. Check the cache backend (localStorage by default; override via `cache`)
2797
2838
  * 2. If cache valid and not force refresh, return cached tools
2798
2839
  * 3. Otherwise, fetch from API, cache, and return
2799
2840
  * 4. On fetch failure, return cached tools if available (stale-while-error)
@@ -3085,6 +3126,11 @@ interface SelectServerToolsForPromptOptions {
3085
3126
  embeddingModel?: string;
3086
3127
  /** Cache expiration in ms for the server-tools catalog fetch. */
3087
3128
  cacheExpirationMs?: number;
3129
+ /**
3130
+ * Where to read/write the cached catalog. Defaults to browser `localStorage`
3131
+ * (a no-op on Node/RN); pass a backend to persist on those platforms.
3132
+ */
3133
+ cache?: ToolsCacheBackend;
3088
3134
  /**
3089
3135
  * Phase 3 defer-loading. When `enabled`, this helper returns the FULL catalog (skipping semantic/
3090
3136
  * static filtering) to mirror useChatStorage's responses send path, which swaps in the full catalog
@@ -5366,11 +5412,26 @@ interface EmbeddingOptions {
5366
5412
  }
5367
5413
 
5368
5414
  /**
5369
- * Memory Retrieval Embeddings
5415
+ * Embedding generation — dependency-free core.
5416
+ *
5417
+ * The raw "text → embedding" calls, split out of `embeddings.ts` so they can be
5418
+ * imported by node/React-Native-safe modules (the server-tool + client-tool
5419
+ * selection engine in `../tools`) WITHOUT pulling in the WatermelonDB-backed
5420
+ * `db/chat/operations` that `embeddings.ts` needs for its message-persistence
5421
+ * helpers (`embedMessage`, `embedAllMessages`, `chunkAndEmbed*`).
5370
5422
  *
5371
- * Functions for generating and storing embeddings for conversation messages.
5423
+ * Nothing here touches the database; the only I/O is the HTTP embeddings
5424
+ * endpoint. `embeddings.ts` re-exports these so existing importers of
5425
+ * `../memoryEngine/embeddings` (and the `../memoryEngine` barrel) keep working.
5372
5426
  */
5373
5427
 
5428
+ /**
5429
+ * Generate an embedding for text using the API
5430
+ *
5431
+ * Supports two auth methods:
5432
+ * - `apiKey`: Uses X-API-Key header (for server-side/CLI usage)
5433
+ * - `getToken`: Uses Authorization: Bearer header (for Privy identity tokens)
5434
+ */
5374
5435
  declare function generateEmbedding(text: string, options: EmbeddingOptions): Promise<number[]>;
5375
5436
  /**
5376
5437
  * Generate embeddings for multiple texts, automatically chunking large inputs.
@@ -5385,6 +5446,18 @@ declare function generateEmbedding(text: string, options: EmbeddingOptions): Pro
5385
5446
  * @returns Array of embeddings in the same order as input texts
5386
5447
  */
5387
5448
  declare function generateEmbeddings(texts: string[], options: EmbeddingOptions): Promise<number[][]>;
5449
+
5450
+ /**
5451
+ * Memory Retrieval Embeddings
5452
+ *
5453
+ * Message-level embedding + persistence helpers: find messages via the
5454
+ * WatermelonDB-backed `db/chat/operations`, embed their content, and store the
5455
+ * vectors/chunks back. The raw "text → embedding" calls live in `./generate`
5456
+ * (dependency-free so the tool-selection engine can import them without the DB
5457
+ * layer) and are re-exported here so existing importers of
5458
+ * `../memoryEngine/embeddings` and the `../memoryEngine` barrel keep working.
5459
+ */
5460
+
5388
5461
  /**
5389
5462
  * Embed a single message and store the embedding in the database
5390
5463
  *
@@ -6583,14 +6656,14 @@ declare function createChunkVectorCache(maxSize?: number): ChunkVectorCache;
6583
6656
  declare function recall(query: string, ctx: RecallContext, options?: RecallOptions): Promise<RecallResult>;
6584
6657
 
6585
6658
  /**
6586
- * Unified Recall Tool
6659
+ * Recall tool constants — deliberately dependency-free.
6587
6660
  *
6588
- * Single chat-completion tool that searches both vault facts and
6589
- * conversation chunks via `recall()`. Replaces the legacy pair of
6590
- * `memory_vault_search` (facts) + `search_memory` (chunks) — the LLM no
6591
- * longer has to route between two tools.
6661
+ * Split out of `recallTool.ts` so the tool NAME can be referenced from
6662
+ * node/React-Native-safe modules (e.g. the client-tool selector in
6663
+ * `../tools/clientToolSelection`) without dragging `recall()` and its
6664
+ * WatermelonDB-backed operations into the module graph. `recallTool.ts`
6665
+ * re-exports these to preserve their public identity.
6592
6666
  */
6593
-
6594
6667
  /** Tool name surfaced to the LLM. Exported so bench harnesses and chat
6595
6668
  * clients reference the same string — drift between prod and bench would
6596
6669
  * mask tool-routing bugs in eval. */
@@ -6598,6 +6671,16 @@ declare const RECALL_TOOL_NAME = "recall_memory";
6598
6671
  /** Maximum results the executor will return to the LLM, regardless of
6599
6672
  * the LLM-supplied `limit`. */
6600
6673
  declare const RECALL_MAX_LIMIT = 50;
6674
+
6675
+ /**
6676
+ * Unified Recall Tool
6677
+ *
6678
+ * Single chat-completion tool that searches both vault facts and
6679
+ * conversation chunks via `recall()`. Replaces the legacy pair of
6680
+ * `memory_vault_search` (facts) + `search_memory` (chunks) — the LLM no
6681
+ * longer has to route between two tools.
6682
+ */
6683
+
6601
6684
  interface RecallToolOptions {
6602
6685
  /** Lanes to search. Default: ["fact", "chunk"]. */
6603
6686
  types?: MemoryKind[];
@@ -22,7 +22,6 @@ import {
22
22
  createConversationOp,
23
23
  createMemoryVaultSearchTool,
24
24
  createMessageOp,
25
- createSseClient,
26
25
  createSupersedingMemoryOp,
27
26
  createVaultEmbeddingCache,
28
27
  createVaultMemoriesBatchOp,
@@ -108,7 +107,7 @@ import {
108
107
  updateVaultMemoryOp,
109
108
  upsertMessageOp,
110
109
  vaultMemoryToStored
111
- } from "./chunk-QQOIC37O.mjs";
110
+ } from "./chunk-RKUNGNBF.mjs";
112
111
  import {
113
112
  createStreamingDeAnonymizer,
114
113
  resolvePiiRedactor
@@ -5501,9 +5500,11 @@ function createChunkVectorCache(maxSize = DEFAULT_CHUNK_CACHE_SIZE) {
5501
5500
  return new LRUCache(maxSize);
5502
5501
  }
5503
5502
 
5504
- // src/lib/memory/recallTool.ts
5503
+ // src/lib/memory/recallConstants.ts
5505
5504
  var RECALL_TOOL_NAME = "recall_memory";
5506
5505
  var RECALL_MAX_LIMIT = 50;
5506
+
5507
+ // src/lib/memory/recallTool.ts
5507
5508
  var DEFAULT_LIMIT = 8;
5508
5509
  var DEFAULT_BUDGET = "low";
5509
5510
  function formatEventTime(start, end, kind) {
@@ -6062,7 +6063,7 @@ function getCachedServerTools() {
6062
6063
  if (!cached) return null;
6063
6064
  const parsed = JSON.parse(cached);
6064
6065
  if (parsed.version !== CACHE_VERSION) {
6065
- clearServerToolsCache();
6066
+ removeLocalStorageCache();
6066
6067
  return null;
6067
6068
  }
6068
6069
  return parsed;
@@ -6074,37 +6075,45 @@ function isCacheExpired(cache, expirationMs = DEFAULT_CACHE_EXPIRATION_MS) {
6074
6075
  if (!cache) return true;
6075
6076
  return Date.now() - cache.timestamp > expirationMs;
6076
6077
  }
6077
- function cacheServerTools(tools, checksum) {
6078
- if (typeof localStorage === "undefined") return;
6079
- const cacheData = {
6078
+ function buildCacheEntry(tools, checksum) {
6079
+ return {
6080
6080
  tools,
6081
6081
  timestamp: Date.now(),
6082
6082
  version: CACHE_VERSION,
6083
6083
  ...checksum && { checksum }
6084
6084
  };
6085
+ }
6086
+ function writeLocalStorageCache(entry) {
6087
+ if (typeof localStorage === "undefined") return;
6085
6088
  try {
6086
- localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(cacheData));
6089
+ localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(entry));
6087
6090
  } catch (error) {
6088
6091
  getLogger().warn("[serverTools] Failed to cache tools:", error);
6089
6092
  }
6090
6093
  }
6091
- function clearServerToolsCache() {
6094
+ function removeLocalStorageCache() {
6092
6095
  if (typeof localStorage === "undefined") return;
6093
6096
  localStorage.removeItem(SERVER_TOOLS_CACHE_KEY);
6094
6097
  }
6095
- function getToolsChecksum() {
6096
- const cached = getCachedServerTools();
6097
- return cached?.checksum;
6098
+ var localStorageToolsCache = {
6099
+ get: getCachedServerTools,
6100
+ set: writeLocalStorageCache,
6101
+ clear: removeLocalStorageCache
6102
+ };
6103
+ function clearServerToolsCache(cache = localStorageToolsCache) {
6104
+ return cache.clear?.();
6105
+ }
6106
+ function getToolsChecksum(cache = localStorageToolsCache) {
6107
+ const cached = cache.get();
6108
+ return cached instanceof Promise ? cached.then((c) => c?.checksum) : cached?.checksum;
6098
6109
  }
6099
- function shouldRefreshTools(responseChecksum) {
6110
+ function shouldRefreshTools(responseChecksum, cache = localStorageToolsCache) {
6100
6111
  if (!responseChecksum) {
6101
6112
  return false;
6102
6113
  }
6103
- const cachedChecksum = getToolsChecksum();
6104
- if (!cachedChecksum) {
6105
- return true;
6106
- }
6107
- return cachedChecksum !== responseChecksum;
6114
+ const decide = (cachedChecksum2) => !cachedChecksum2 || cachedChecksum2 !== responseChecksum;
6115
+ const cachedChecksum = getToolsChecksum(cache);
6116
+ return cachedChecksum instanceof Promise ? cachedChecksum.then(decide) : decide(cachedChecksum);
6108
6117
  }
6109
6118
  async function fetchServerToolsFromApi(baseUrl, token) {
6110
6119
  const response = await fetch(`${baseUrl}/api/v1/tools`, {
@@ -6126,9 +6135,23 @@ async function getServerTools(options) {
6126
6135
  cacheExpirationMs = DEFAULT_CACHE_EXPIRATION_MS,
6127
6136
  forceRefresh = false,
6128
6137
  getToken,
6129
- apiKey
6138
+ apiKey,
6139
+ cache = localStorageToolsCache
6130
6140
  } = options;
6131
- const cached = getCachedServerTools();
6141
+ const persistCache = async (entry) => {
6142
+ try {
6143
+ await cache.set(entry);
6144
+ } catch (error) {
6145
+ getLogger().warn("[serverTools] Cache write failed (non-fatal):", error);
6146
+ }
6147
+ };
6148
+ let rawCached = null;
6149
+ try {
6150
+ rawCached = await cache.get();
6151
+ } catch (error) {
6152
+ getLogger().warn("[serverTools] Cache read failed; falling through to server fetch:", error);
6153
+ }
6154
+ const cached = rawCached && rawCached.version === CACHE_VERSION ? rawCached : null;
6132
6155
  const cacheValid = !isCacheExpired(cached, cacheExpirationMs);
6133
6156
  if (cached && cacheValid && !forceRefresh) {
6134
6157
  return cached.tools;
@@ -6149,7 +6172,7 @@ async function getServerTools(options) {
6149
6172
  }
6150
6173
  const data = await response.json();
6151
6174
  const { tools: tools2, checksum: checksum2 } = convertServerToolsResponse(data);
6152
- cacheServerTools(tools2, checksum2);
6175
+ await persistCache(buildCacheEntry(tools2, checksum2));
6153
6176
  return tools2;
6154
6177
  }
6155
6178
  if (!getToken) {
@@ -6162,7 +6185,7 @@ async function getServerTools(options) {
6162
6185
  return cached?.tools ?? [];
6163
6186
  }
6164
6187
  const { tools, checksum } = await fetchServerToolsFromApi(effectiveBaseUrl, token);
6165
- cacheServerTools(tools, checksum);
6188
+ await persistCache(buildCacheEntry(tools, checksum));
6166
6189
  return tools;
6167
6190
  } catch (error) {
6168
6191
  getLogger().error("[serverTools] Failed to fetch server tools:", error);
@@ -6546,13 +6569,14 @@ async function selectServerToolsForPrompt(options) {
6546
6569
  baseUrl,
6547
6570
  embeddingModel,
6548
6571
  cacheExpirationMs,
6572
+ cache,
6549
6573
  deferLoading
6550
6574
  } = options;
6551
6575
  if (serverToolsFilter === void 0) return [];
6552
6576
  if (Array.isArray(serverToolsFilter) && serverToolsFilter.length === 0) return [];
6553
6577
  let allServerTools;
6554
6578
  try {
6555
- allServerTools = await getServerTools({ baseUrl, cacheExpirationMs, getToken });
6579
+ allServerTools = await getServerTools({ baseUrl, cacheExpirationMs, getToken, cache });
6556
6580
  } catch {
6557
6581
  return [];
6558
6582
  }
@@ -7887,6 +7911,141 @@ function createCryptoPricePreProcessor(options = {}) {
7887
7911
  };
7888
7912
  }
7889
7913
 
7914
+ // src/client/core/serverSentEvents.gen.ts
7915
+ var createSseClient = ({
7916
+ onRequest,
7917
+ onSseError,
7918
+ onSseEvent,
7919
+ responseTransformer,
7920
+ responseValidator,
7921
+ sseDefaultRetryDelay,
7922
+ sseMaxRetryAttempts,
7923
+ sseMaxRetryDelay,
7924
+ sseSleepFn,
7925
+ url,
7926
+ ...options
7927
+ }) => {
7928
+ let lastEventId;
7929
+ const sleep3 = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
7930
+ const createStream = async function* () {
7931
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
7932
+ let attempt = 0;
7933
+ const signal = options.signal ?? new AbortController().signal;
7934
+ while (true) {
7935
+ if (signal.aborted) break;
7936
+ attempt++;
7937
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
7938
+ if (lastEventId !== void 0) {
7939
+ headers.set("Last-Event-ID", lastEventId);
7940
+ }
7941
+ try {
7942
+ const requestInit = {
7943
+ redirect: "follow",
7944
+ ...options,
7945
+ body: options.serializedBody,
7946
+ headers,
7947
+ signal
7948
+ };
7949
+ let request = new Request(url, requestInit);
7950
+ if (onRequest) {
7951
+ request = await onRequest(url, requestInit);
7952
+ }
7953
+ const _fetch = options.fetch ?? globalThis.fetch;
7954
+ const response = await _fetch(request);
7955
+ if (!response.ok)
7956
+ throw new Error(
7957
+ `SSE failed: ${response.status} ${response.statusText}`
7958
+ );
7959
+ if (!response.body) throw new Error("No body in SSE response");
7960
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
7961
+ let buffer = "";
7962
+ const abortHandler = () => {
7963
+ try {
7964
+ reader.cancel();
7965
+ } catch {
7966
+ }
7967
+ };
7968
+ signal.addEventListener("abort", abortHandler);
7969
+ try {
7970
+ while (true) {
7971
+ const { done, value } = await reader.read();
7972
+ if (done) break;
7973
+ buffer += value;
7974
+ const chunks = buffer.split("\n\n");
7975
+ buffer = chunks.pop() ?? "";
7976
+ for (const chunk of chunks) {
7977
+ const lines = chunk.split("\n");
7978
+ const dataLines = [];
7979
+ let eventName;
7980
+ for (const line of lines) {
7981
+ if (line.startsWith("data:")) {
7982
+ dataLines.push(line.replace(/^data:\s*/, ""));
7983
+ } else if (line.startsWith("event:")) {
7984
+ eventName = line.replace(/^event:\s*/, "");
7985
+ } else if (line.startsWith("id:")) {
7986
+ lastEventId = line.replace(/^id:\s*/, "");
7987
+ } else if (line.startsWith("retry:")) {
7988
+ const parsed = Number.parseInt(
7989
+ line.replace(/^retry:\s*/, ""),
7990
+ 10
7991
+ );
7992
+ if (!Number.isNaN(parsed)) {
7993
+ retryDelay = parsed;
7994
+ }
7995
+ }
7996
+ }
7997
+ let data;
7998
+ let parsedJson = false;
7999
+ if (dataLines.length) {
8000
+ const rawData = dataLines.join("\n");
8001
+ try {
8002
+ data = JSON.parse(rawData);
8003
+ parsedJson = true;
8004
+ } catch {
8005
+ data = rawData;
8006
+ }
8007
+ }
8008
+ if (parsedJson) {
8009
+ if (responseValidator) {
8010
+ await responseValidator(data);
8011
+ }
8012
+ if (responseTransformer) {
8013
+ data = await responseTransformer(data);
8014
+ }
8015
+ }
8016
+ onSseEvent?.({
8017
+ data,
8018
+ event: eventName,
8019
+ id: lastEventId,
8020
+ retry: retryDelay
8021
+ });
8022
+ if (dataLines.length) {
8023
+ yield data;
8024
+ }
8025
+ }
8026
+ }
8027
+ } finally {
8028
+ signal.removeEventListener("abort", abortHandler);
8029
+ reader.releaseLock();
8030
+ }
8031
+ break;
8032
+ } catch (error) {
8033
+ onSseError?.(error);
8034
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
8035
+ break;
8036
+ }
8037
+ const backoff = Math.min(
8038
+ retryDelay * 2 ** (attempt - 1),
8039
+ sseMaxRetryDelay ?? 3e4
8040
+ );
8041
+ await sleep3(backoff);
8042
+ }
8043
+ }
8044
+ };
8045
+ const stream = createStream();
8046
+ return { stream };
8047
+ };
8048
+
7890
8049
  // src/lib/chat/runHooks.ts
7891
8050
  function composeHooks(hooks) {
7892
8051
  const handlers = hooks.filter((h) => h !== void 0 && h !== null);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-QQOIC37O.mjs";
3
+ } from "./chunk-RKUNGNBF.mjs";
4
4
  import "./chunk-AHJT66EO.mjs";
5
5
  import "./chunk-3RPGXXPZ.mjs";
6
6
  export {