recursive-llm-ts 4.4.1 → 4.6.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.
package/README.md CHANGED
@@ -6,16 +6,33 @@ TypeScript/JavaScript package for [Recursive Language Models (RLM)](https://gith
6
6
 
7
7
  ## Features
8
8
 
9
- **Pure Go Implementation** - No Python dependencies required
10
- 🚀 **50x Faster Startup** - Native binary vs Python runtime
11
- 💾 **3x Less Memory** - Efficient Go implementation
12
- 📦 **Single Binary** - Easy distribution and deployment
13
- 🔄 **Unbounded Context** - Process 10M+ tokens without degradation
14
- 🎯 **Provider Agnostic** - Works with OpenAI, Anthropic, Azure, Bedrock, local models
15
- 🔍 **Structured Outputs** - Extract typed data with Zod schemas and parallel execution
16
- 🧠 **Meta-Agent Mode** - Automatically optimize queries for better results
17
- 📊 **Observability** - OpenTelemetry tracing, Langfuse integration, and debug logging
18
- 📁 **File Storage** - Process local directories or S3/MinIO/LocalStack buckets as LLM context
9
+ **Core**
10
+ - **Unbounded Context** - Process 10M+ tokens without degradation via recursive decomposition
11
+ - **Structured Outputs** - Extract typed data with Zod schemas, parallel execution, and instructor-style retry
12
+ - **Streaming** - Progressive text output and partial structured objects via async iterables
13
+ - **Batch Operations** - Process multiple queries in parallel with concurrency control
14
+
15
+ **Performance & Resilience**
16
+ - **Pure Go Backend** - 50x faster startup, 3x less memory vs Python
17
+ - **Context Overflow Recovery** - Automatic detection and 6 reduction strategies (mapreduce, truncate, chunked, tfidf, textrank, refine)
18
+ - **Caching** - Exact-match caching with in-memory and file-based backends
19
+ - **Retry & Fallback** - Exponential backoff, jitter, and multi-provider fallback chains
20
+ - **AbortController** - Cancel any operation mid-flight
21
+
22
+ **Developer Experience**
23
+ - **Typed Errors** - Rich error hierarchy with codes, retryable flags, and suggestions
24
+ - **Event System** - Monitor LLM calls, cache hits, retries, and errors in real-time
25
+ - **Builder API** - Fluent configuration with full IDE discoverability
26
+ - **Factory Methods** - `RLM.fromEnv()`, `RLM.withDebug()`, `RLM.forAzure()`
27
+ - **Config Validation** - Catches typos and invalid settings at construction time
28
+ - **Result Formatters** - `prettyStats()`, `toJSON()`, `toMarkdown()`
29
+
30
+ **Ecosystem**
31
+ - **Provider Agnostic** - Works with OpenAI, Anthropic, Azure, Bedrock, local models
32
+ - **Meta-Agent Mode** - Automatically optimize queries for better results
33
+ - **Observability** - OpenTelemetry tracing, Langfuse integration, and debug logging
34
+ - **File Storage** - Process local directories or S3/MinIO/LocalStack buckets as LLM context
35
+ - **150+ Tests** - Comprehensive Vitest + Go test suites
19
36
 
20
37
  ## Installation
21
38
 
@@ -131,6 +148,236 @@ const result = await rlm.structuredCompletion(
131
148
  );
132
149
  ```
133
150
 
151
+ ### Streaming
152
+
153
+ Get progressive output with async iterables and AbortController support:
154
+
155
+ ```typescript
156
+ // Stream text output
157
+ const stream = rlm.streamCompletion('Summarize', longDocument);
158
+ for await (const chunk of stream) {
159
+ if (chunk.type === 'text') process.stdout.write(chunk.text);
160
+ }
161
+
162
+ // Collect all text
163
+ const text = await rlm.streamCompletion('Summarize', doc).toText();
164
+
165
+ // Cancel mid-stream
166
+ const controller = new AbortController();
167
+ const stream = rlm.streamCompletion('Summarize', doc, { signal: controller.signal });
168
+ setTimeout(() => controller.abort(), 5000);
169
+ ```
170
+
171
+ ### Caching
172
+
173
+ Avoid redundant API calls with exact-match caching:
174
+
175
+ ```typescript
176
+ const rlm = new RLM('gpt-4o-mini', {
177
+ api_key: process.env.OPENAI_API_KEY,
178
+ cache: {
179
+ enabled: true,
180
+ strategy: 'exact', // 'exact' | 'none'
181
+ maxEntries: 1000,
182
+ ttl: 3600, // seconds
183
+ storage: 'memory', // 'memory' | 'file'
184
+ }
185
+ });
186
+
187
+ const r1 = await rlm.completion('Summarize', doc); // API call
188
+ const r2 = await rlm.completion('Summarize', doc); // Cache hit!
189
+ console.log(r2.cached); // true
190
+ console.log(rlm.getCacheStats()); // { hits: 1, misses: 1, hitRate: 0.5, ... }
191
+ ```
192
+
193
+ ### Retry & Resilience
194
+
195
+ Automatic retry with exponential backoff and provider fallback:
196
+
197
+ ```typescript
198
+ const rlm = new RLM('gpt-4o-mini', {
199
+ api_key: process.env.OPENAI_API_KEY,
200
+ retry: {
201
+ maxRetries: 3,
202
+ backoff: 'exponential', // 1s, 2s, 4s with jitter
203
+ onRetry: (attempt, error, delay) => {
204
+ console.log(`Retry ${attempt} after ${delay}ms: ${error.message}`);
205
+ },
206
+ },
207
+ });
208
+
209
+ // Or use standalone retry/fallback utilities:
210
+ import { withRetry, withFallback } from 'recursive-llm-ts';
211
+
212
+ const result = await withFallback(
213
+ (model) => rlm.completion(query, context),
214
+ { models: ['gpt-4o', 'claude-sonnet-4-20250514', 'gemini-2.0-flash'] }
215
+ );
216
+ ```
217
+
218
+ ### Event System
219
+
220
+ Monitor operations in real-time:
221
+
222
+ ```typescript
223
+ const rlm = new RLM('gpt-4o-mini', { api_key: process.env.OPENAI_API_KEY });
224
+
225
+ rlm.on('llm_call', (e) => console.log(`Calling ${e.model}...`));
226
+ rlm.on('llm_response', (e) => console.log(`Response in ${e.duration}ms`));
227
+ rlm.on('cache', (e) => console.log(`Cache ${e.action}`));
228
+ rlm.on('error', (e) => reportToSentry(e.error));
229
+ rlm.on('completion_start', (e) => showSpinner());
230
+ rlm.on('completion_end', (e) => hideSpinner());
231
+ ```
232
+
233
+ ### Builder API
234
+
235
+ Fluent configuration with full IDE discoverability:
236
+
237
+ ```typescript
238
+ const rlm = RLM.builder('gpt-4o-mini')
239
+ .apiKey(process.env.OPENAI_API_KEY!)
240
+ .maxDepth(10)
241
+ .maxIterations(30)
242
+ .withMetaAgent({ model: 'gpt-4o' })
243
+ .withDebug()
244
+ .withCache({ strategy: 'exact' })
245
+ .withRetry({ maxRetries: 3 })
246
+ .withFallback(['gpt-4o', 'claude-sonnet-4-20250514'])
247
+ .build();
248
+ ```
249
+
250
+ ### Factory Methods
251
+
252
+ Quick setup for common configurations:
253
+
254
+ ```typescript
255
+ // From environment variables
256
+ const rlm = RLM.fromEnv('gpt-4o-mini');
257
+
258
+ // Debug mode
259
+ const rlm = RLM.withDebug('gpt-4o-mini');
260
+
261
+ // Azure OpenAI
262
+ const rlm = RLM.forAzure('my-deployment', {
263
+ apiBase: 'https://myresource.openai.azure.com',
264
+ apiVersion: '2024-02-15-preview',
265
+ });
266
+ ```
267
+
268
+ ### Batch Operations
269
+
270
+ Process multiple queries in parallel:
271
+
272
+ ```typescript
273
+ const results = await rlm.batchCompletion([
274
+ { query: 'Summarize chapter 1', context: ch1 },
275
+ { query: 'Summarize chapter 2', context: ch2 },
276
+ { query: 'Summarize chapter 3', context: ch3 },
277
+ ], { concurrency: 2 });
278
+ ```
279
+
280
+ ### Error Handling
281
+
282
+ Rich error hierarchy with actionable information:
283
+
284
+ ```typescript
285
+ import {
286
+ RLMRateLimitError, RLMValidationError,
287
+ RLMTimeoutError, RLMContextOverflowError
288
+ } from 'recursive-llm-ts';
289
+
290
+ try {
291
+ const result = await rlm.completion(query, context);
292
+ } catch (err) {
293
+ if (err instanceof RLMContextOverflowError) {
294
+ console.log(`Context overflow: ${err.requestTokens} tokens > ${err.modelLimit} limit`);
295
+ // Enable context_overflow config to auto-recover from this
296
+ } else if (err instanceof RLMRateLimitError) {
297
+ console.log(`Rate limited. Retry after: ${err.retryAfter}s`);
298
+ } else if (err instanceof RLMValidationError) {
299
+ console.log(`Schema mismatch:`, err.zodErrors);
300
+ } else if (err instanceof RLMTimeoutError) {
301
+ console.log(`Timed out after ${err.elapsed}ms`);
302
+ }
303
+ // All RLM errors have: err.code, err.retryable, err.suggestion
304
+ }
305
+ ```
306
+
307
+ ### Context Overflow Handling
308
+
309
+ Automatically detect and recover from context window overflows. When your input exceeds the model's token limit, RLM catches the error and applies a reduction strategy to fit the context within bounds.
310
+
311
+ ```typescript
312
+ const rlm = new RLM('gpt-4o-mini', {
313
+ api_key: process.env.OPENAI_API_KEY,
314
+ context_overflow: {
315
+ enabled: true, // Enable overflow recovery (default: true)
316
+ strategy: 'tfidf', // Reduction strategy (see table below)
317
+ max_model_tokens: 32768, // Override auto-detected limit (optional)
318
+ safety_margin: 0.15, // Reserve 15% for prompts/overhead (default: 0.15)
319
+ max_reduction_attempts: 3, // Max retry attempts (default: 3)
320
+ }
321
+ });
322
+
323
+ // Process a document that may exceed the model's context window
324
+ const result = await rlm.completion(
325
+ 'Summarize the key findings',
326
+ veryLargeDocument // If too large, auto-reduces and retries
327
+ );
328
+ ```
329
+
330
+ **Builder API:**
331
+ ```typescript
332
+ const rlm = RLM.builder('gpt-4o-mini')
333
+ .apiKey(process.env.OPENAI_API_KEY!)
334
+ .withContextOverflow({ strategy: 'textrank', max_model_tokens: 32768 })
335
+ .build();
336
+ ```
337
+
338
+ **Strategy Comparison:**
339
+
340
+ | Strategy | API Calls | Speed | Quality | Best For |
341
+ |----------|-----------|-------|---------|----------|
342
+ | `mapreduce` | Many (parallel) | Medium | High | General-purpose, large documents |
343
+ | `truncate` | 0 | Fastest | Low | Quick-and-dirty, when beginning of doc matters |
344
+ | `chunked` | Many (sequential) | Slow | High | Detailed extraction from specific sections |
345
+ | `tfidf` | 0 | Fast | Medium | Fast first pass, keyword-rich documents |
346
+ | `textrank` | 0 | Fast | Medium-High | Documents with clear sentence structure |
347
+ | `refine` | Many (sequential) | Slow | Highest | When quality matters most, iterative refinement |
348
+
349
+ **Strategy Details:**
350
+
351
+ - **`mapreduce`** (default) - Splits context into chunks, summarizes each in parallel via LLM calls, then merges summaries. Good balance of quality and speed.
352
+ - **`truncate`** - Drops tokens from the end to fit the budget. Zero API calls, but loses information. Best when the beginning of the document is most important.
353
+ - **`chunked`** - Processes chunks sequentially, extracting relevant content from each. Higher quality than mapreduce for targeted extraction.
354
+ - **`tfidf`** - Pure Go, zero API calls. Uses TF-IDF scoring to select the most informative sentences. Preserves original document order. Great for a fast, no-cost first pass.
355
+ - **`textrank`** - Pure Go, zero API calls. Graph-based sentence ranking using PageRank over cosine-similarity of TF-IDF vectors. Better at identifying structurally important sentences than plain TF-IDF.
356
+ - **`refine`** - Sequential iterative refinement. Processes chunks one at a time, building and refining an answer progressively. Highest quality but slowest, as each chunk sees the accumulated context.
357
+
358
+ ### Config Validation
359
+
360
+ Catch configuration issues at construction time:
361
+
362
+ ```typescript
363
+ const rlm = new RLM('gpt-4o-mini', { max_detph: 5 }); // typo!
364
+ const result = rlm.validate();
365
+ // result.issues: [{ level: 'warning', field: 'max_detph', message: 'Unknown config key...' }]
366
+ ```
367
+
368
+ ### Result Formatting
369
+
370
+ ```typescript
371
+ const result = await rlm.completion(query, context);
372
+ const formatted = rlm.formatResult(result);
373
+
374
+ console.log(formatted.prettyStats());
375
+ // "LLM Calls: 3 | Iterations: 12 | Depth: 2"
376
+
377
+ console.log(formatted.toMarkdown());
378
+ // Full markdown-formatted result with stats table
379
+ ```
380
+
134
381
  ### Agent Coordinator (Advanced)
135
382
 
136
383
  For complex multi-field schemas, use the coordinator API:
@@ -463,6 +710,42 @@ Process a query using files from local or S3 storage as context.
463
710
 
464
711
  Extract structured data from file-based context.
465
712
 
713
+ #### `streamCompletion(query, context, options?): RLMStream`
714
+
715
+ Stream a completion with progressive text output. Returns an async iterable.
716
+
717
+ #### `streamStructuredCompletion<T>(query, context, schema, options?): RLMStream<T>`
718
+
719
+ Stream a structured completion with partial object updates.
720
+
721
+ #### `batchCompletion(queries, options?): Promise<Array<RLMCompletionResult | Error>>`
722
+
723
+ Execute multiple completions in parallel with concurrency control.
724
+
725
+ #### `batchStructuredCompletion<T>(queries, options?): Promise<Array<StructuredRLMResult<T> | Error>>`
726
+
727
+ Execute multiple structured completions in parallel.
728
+
729
+ #### `validate(): ValidationResult`
730
+
731
+ Validate the current configuration without making API calls.
732
+
733
+ #### `getCacheStats(): CacheStats`
734
+
735
+ Get cache performance statistics (hits, misses, hit rate).
736
+
737
+ #### `clearCache(): void`
738
+
739
+ Clear the completion cache.
740
+
741
+ #### `formatResult(result): RLMResultFormatter`
742
+
743
+ Create a formatted result with `prettyStats()`, `toJSON()`, `toMarkdown()`.
744
+
745
+ #### `on(event, listener) / off(event, listener) / once(event, listener)`
746
+
747
+ Register/remove event listeners. Events: `llm_call`, `llm_response`, `error`, `cache`, `completion_start`, `completion_end`, `retry`, `validation_retry`, `meta_agent`, `recursion`.
748
+
466
749
  #### `cleanup(): Promise<void>`
467
750
 
468
751
  Clean up the bridge and free resources.
@@ -508,12 +791,50 @@ interface RLMConfig {
508
791
  // Shorthand for observability.debug
509
792
  debug?: boolean;
510
793
 
511
- // LiteLLM parameters - pass any additional parameters supported by LiteLLM
794
+ // LiteLLM parameters
512
795
  api_version?: string; // API version (e.g., for Azure)
513
796
  timeout?: number; // Request timeout in seconds
514
797
  temperature?: number; // Sampling temperature
515
798
  max_tokens?: number; // Maximum tokens in response
516
- [key: string]: any; // Any other LiteLLM parameters
799
+
800
+ // Context overflow recovery
801
+ context_overflow?: ContextOverflowConfig;
802
+
803
+ // Caching, retry, fallback
804
+ cache?: CacheConfig; // Cache configuration
805
+ retry?: RetryConfig; // Retry configuration
806
+ fallback?: FallbackConfig; // Fallback model configuration
807
+ }
808
+
809
+ interface CacheConfig {
810
+ enabled?: boolean; // Enable caching (default: false)
811
+ strategy?: 'exact' | 'none'; // Cache strategy (default: 'exact')
812
+ maxEntries?: number; // Max cached entries (default: 1000)
813
+ ttl?: number; // Time-to-live in seconds (default: 3600)
814
+ storage?: 'memory' | 'file'; // Storage backend (default: 'memory')
815
+ cacheDir?: string; // Dir for file cache (default: '.rlm-cache')
816
+ }
817
+
818
+ interface RetryConfig {
819
+ maxRetries?: number; // Max retries (default: 3)
820
+ backoff?: 'exponential' | 'linear' | 'fixed';
821
+ baseDelay?: number; // Base delay ms (default: 1000)
822
+ maxDelay?: number; // Max delay ms (default: 30000)
823
+ jitter?: boolean; // Add jitter (default: true)
824
+ onRetry?: (attempt: number, error: Error, delay: number) => void;
825
+ }
826
+
827
+ interface FallbackConfig {
828
+ models?: string[]; // Ordered fallback models
829
+ strategy?: 'sequential'; // Fallback strategy
830
+ }
831
+
832
+ interface ContextOverflowConfig {
833
+ enabled?: boolean; // Enable overflow recovery (default: true)
834
+ max_model_tokens?: number; // Override auto-detected model limit (0 = auto-detect)
835
+ strategy?: 'mapreduce' | 'truncate' | 'chunked' | 'tfidf' | 'textrank' | 'refine';
836
+ safety_margin?: number; // Fraction to reserve for overhead (default: 0.15)
837
+ max_reduction_attempts?: number; // Max reduction retries (default: 3)
517
838
  }
518
839
 
519
840
  interface MetaAgentConfig {
@@ -583,6 +904,22 @@ interface FileStorageResult {
583
904
  totalSize: number;
584
905
  skipped: Array<{ relativePath: string; reason: string }>;
585
906
  }
907
+
908
+ // Error hierarchy - all extend RLMError
909
+ class RLMError extends Error {
910
+ code: string; // Machine-readable: "RATE_LIMIT", "VALIDATION", etc.
911
+ retryable: boolean; // Whether caller should retry
912
+ suggestion?: string; // Human-readable fix suggestion
913
+ }
914
+ class RLMValidationError extends RLMError { expected; received; zodErrors; }
915
+ class RLMRateLimitError extends RLMError { retryAfter?: number; }
916
+ class RLMTimeoutError extends RLMError { elapsed; limit; }
917
+ class RLMProviderError extends RLMError { statusCode; provider; }
918
+ class RLMBinaryError extends RLMError { binaryPath; }
919
+ class RLMConfigError extends RLMError { field; value; }
920
+ class RLMContextOverflowError extends RLMError { modelLimit; requestTokens; }
921
+ class RLMSchemaError extends RLMError { path; constraint; }
922
+ class RLMAbortError extends RLMError {}
586
923
  ```
587
924
 
588
925
  ## Environment Variables
@@ -882,6 +1219,32 @@ The recursive-llm approach breaks down large contexts into manageable chunks and
882
1219
  - ✅ **Type-safe** - Full TypeScript type definitions
883
1220
  - ✅ **Simple API** - Just `npm install` and start using
884
1221
 
1222
+ ## Testing
1223
+
1224
+ ```bash
1225
+ # Run all tests (Vitest)
1226
+ npm test
1227
+
1228
+ # Watch mode
1229
+ npm run test:watch
1230
+
1231
+ # Coverage
1232
+ npm run test:coverage
1233
+
1234
+ # Type-check
1235
+ npm run typecheck
1236
+
1237
+ # Go tests
1238
+ cd go && go test ./rlm/... -v
1239
+ ```
1240
+
1241
+ ## Documentation
1242
+
1243
+ - [Quick Start Guide](docs/QUICKSTART.md)
1244
+ - [Architecture Overview](docs/ARCHITECTURE.md)
1245
+ - [Contributing Guide](CONTRIBUTING.md)
1246
+ - [UX/DX Gap Analysis](docs/UX-DX-GAP-ANALYSIS.md)
1247
+
885
1248
  ## Publishing
886
1249
 
887
1250
  This package uses automated GitHub Actions workflows to publish to npm. See [RELEASE.md](RELEASE.md) for detailed instructions on publishing new versions.
package/bin/rlm-go CHANGED
Binary file
@@ -5,7 +5,7 @@ export interface RLMStats {
5
5
  parsing_retries?: number;
6
6
  }
7
7
  export interface RLMResult {
8
- result: string | any;
8
+ result: string;
9
9
  stats: RLMStats;
10
10
  structured_result?: boolean;
11
11
  trace_events?: TraceEvent[];
@@ -36,6 +36,18 @@ export interface TraceEvent {
36
36
  span_id?: string;
37
37
  parent_id?: string;
38
38
  }
39
+ export interface ContextOverflowConfig {
40
+ /** Enable automatic context overflow recovery (default: true) */
41
+ enabled?: boolean;
42
+ /** Override detected model token limit (0 = auto-detect from API errors) */
43
+ max_model_tokens?: number;
44
+ /** Strategy: 'mapreduce' (default), 'truncate', 'chunked', 'tfidf', 'textrank', or 'refine' */
45
+ strategy?: 'mapreduce' | 'truncate' | 'chunked' | 'tfidf' | 'textrank' | 'refine';
46
+ /** Fraction of token budget to reserve for prompts/overhead (default: 0.15) */
47
+ safety_margin?: number;
48
+ /** Maximum reduction attempts before giving up (default: 3) */
49
+ max_reduction_attempts?: number;
50
+ }
39
51
  export interface RLMConfig {
40
52
  recursive_model?: string;
41
53
  api_base?: string;
@@ -46,8 +58,13 @@ export interface RLMConfig {
46
58
  go_binary_path?: string;
47
59
  meta_agent?: MetaAgentConfig;
48
60
  observability?: ObservabilityConfig;
61
+ context_overflow?: ContextOverflowConfig;
49
62
  debug?: boolean;
50
- [key: string]: any;
63
+ api_version?: string;
64
+ timeout?: number;
65
+ temperature?: number;
66
+ max_tokens?: number;
67
+ structured?: any;
51
68
  }
52
69
  export interface FileStorageConfig {
53
70
  /** Storage type: 'local' or 's3' */
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Caching layer for recursive-llm-ts completions.
3
+ *
4
+ * Provides exact-match caching to avoid redundant API calls for
5
+ * identical query+context pairs. Supports in-memory and file-based storage.
6
+ */
7
+ export interface CacheConfig {
8
+ /** Enable/disable caching (default: false) */
9
+ enabled?: boolean;
10
+ /** Cache strategy (default: 'exact') */
11
+ strategy?: 'exact' | 'none';
12
+ /** Maximum number of cached entries (default: 1000) */
13
+ maxEntries?: number;
14
+ /** Time-to-live in seconds (default: 3600 = 1 hour) */
15
+ ttl?: number;
16
+ /** Storage backend (default: 'memory') */
17
+ storage?: 'memory' | 'file';
18
+ /** Directory for file-based cache (default: .rlm-cache) */
19
+ cacheDir?: string;
20
+ }
21
+ export interface CacheStats {
22
+ hits: number;
23
+ misses: number;
24
+ size: number;
25
+ hitRate: number;
26
+ evictions: number;
27
+ }
28
+ export interface CacheProvider {
29
+ get<T>(key: string): T | undefined;
30
+ set<T>(key: string, value: T, ttl: number): void;
31
+ has(key: string): boolean;
32
+ delete(key: string): boolean;
33
+ clear(): void;
34
+ size(): number;
35
+ }
36
+ export declare class MemoryCache implements CacheProvider {
37
+ private store;
38
+ private maxEntries;
39
+ constructor(maxEntries?: number);
40
+ get<T>(key: string): T | undefined;
41
+ set<T>(key: string, value: T, ttl: number): void;
42
+ has(key: string): boolean;
43
+ delete(key: string): boolean;
44
+ clear(): void;
45
+ size(): number;
46
+ }
47
+ export declare class FileCache implements CacheProvider {
48
+ private cacheDir;
49
+ private maxEntries;
50
+ constructor(cacheDir?: string, maxEntries?: number);
51
+ private filePath;
52
+ get<T>(key: string): T | undefined;
53
+ set<T>(key: string, value: T, ttl: number): void;
54
+ has(key: string): boolean;
55
+ delete(key: string): boolean;
56
+ clear(): void;
57
+ size(): number;
58
+ }
59
+ export declare class RLMCache {
60
+ private provider;
61
+ private config;
62
+ private stats;
63
+ constructor(config?: CacheConfig);
64
+ /** Check if caching is enabled */
65
+ get enabled(): boolean;
66
+ /** Look up a cached result */
67
+ lookup<T>(model: string, query: string, context: string, extra?: Record<string, unknown>): {
68
+ hit: boolean;
69
+ value?: T;
70
+ };
71
+ /** Store a result in the cache */
72
+ store<T>(model: string, query: string, context: string, value: T, extra?: Record<string, unknown>): void;
73
+ /** Get cache statistics */
74
+ getStats(): CacheStats;
75
+ /** Clear the cache */
76
+ clear(): void;
77
+ private updateHitRate;
78
+ }