recursive-llm-ts 5.1.1 → 5.2.4

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.
Files changed (65) hide show
  1. package/README.md +59 -23
  2. package/dist/{bridge-factory.js → cjs/bridge-factory.js} +25 -1
  3. package/dist/{go-bridge.js → cjs/go-bridge.js} +35 -3
  4. package/dist/cjs/package.json +3 -0
  5. package/dist/cjs/pkg-dir.d.ts +7 -0
  6. package/dist/cjs/pkg-dir.js +79 -0
  7. package/dist/esm/bridge-factory.d.ts +7 -0
  8. package/dist/esm/bridge-factory.js +60 -0
  9. package/dist/esm/bridge-interface.d.ts +269 -0
  10. package/dist/esm/bridge-interface.js +1 -0
  11. package/dist/esm/cache.d.ts +78 -0
  12. package/dist/esm/cache.js +207 -0
  13. package/dist/esm/config.d.ts +37 -0
  14. package/dist/esm/config.js +152 -0
  15. package/dist/esm/coordinator.d.ts +17 -0
  16. package/dist/esm/coordinator.js +41 -0
  17. package/dist/esm/errors.d.ts +113 -0
  18. package/dist/esm/errors.js +205 -0
  19. package/dist/esm/events.d.ts +126 -0
  20. package/dist/esm/events.js +73 -0
  21. package/dist/esm/file-storage.d.ts +122 -0
  22. package/dist/esm/file-storage.js +656 -0
  23. package/dist/esm/go-bridge.d.ts +5 -0
  24. package/dist/esm/go-bridge.js +133 -0
  25. package/dist/esm/index.d.ts +12 -0
  26. package/dist/esm/index.js +17 -0
  27. package/dist/esm/package.json +3 -0
  28. package/dist/esm/pkg-dir.d.ts +7 -0
  29. package/dist/esm/pkg-dir.js +43 -0
  30. package/dist/esm/retry.d.ts +56 -0
  31. package/dist/esm/retry.js +181 -0
  32. package/dist/esm/rlm.d.ts +435 -0
  33. package/dist/esm/rlm.js +1122 -0
  34. package/dist/esm/streaming.d.ts +96 -0
  35. package/dist/esm/streaming.js +205 -0
  36. package/dist/esm/structured-types.d.ts +28 -0
  37. package/dist/esm/structured-types.js +1 -0
  38. package/package.json +20 -8
  39. package/scripts/build-go-binary.js +26 -0
  40. /package/dist/{bridge-factory.d.ts → cjs/bridge-factory.d.ts} +0 -0
  41. /package/dist/{bridge-interface.d.ts → cjs/bridge-interface.d.ts} +0 -0
  42. /package/dist/{bridge-interface.js → cjs/bridge-interface.js} +0 -0
  43. /package/dist/{cache.d.ts → cjs/cache.d.ts} +0 -0
  44. /package/dist/{cache.js → cjs/cache.js} +0 -0
  45. /package/dist/{config.d.ts → cjs/config.d.ts} +0 -0
  46. /package/dist/{config.js → cjs/config.js} +0 -0
  47. /package/dist/{coordinator.d.ts → cjs/coordinator.d.ts} +0 -0
  48. /package/dist/{coordinator.js → cjs/coordinator.js} +0 -0
  49. /package/dist/{errors.d.ts → cjs/errors.d.ts} +0 -0
  50. /package/dist/{errors.js → cjs/errors.js} +0 -0
  51. /package/dist/{events.d.ts → cjs/events.d.ts} +0 -0
  52. /package/dist/{events.js → cjs/events.js} +0 -0
  53. /package/dist/{file-storage.d.ts → cjs/file-storage.d.ts} +0 -0
  54. /package/dist/{file-storage.js → cjs/file-storage.js} +0 -0
  55. /package/dist/{go-bridge.d.ts → cjs/go-bridge.d.ts} +0 -0
  56. /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  57. /package/dist/{index.js → cjs/index.js} +0 -0
  58. /package/dist/{retry.d.ts → cjs/retry.d.ts} +0 -0
  59. /package/dist/{retry.js → cjs/retry.js} +0 -0
  60. /package/dist/{rlm.d.ts → cjs/rlm.d.ts} +0 -0
  61. /package/dist/{rlm.js → cjs/rlm.js} +0 -0
  62. /package/dist/{streaming.d.ts → cjs/streaming.d.ts} +0 -0
  63. /package/dist/{streaming.js → cjs/streaming.js} +0 -0
  64. /package/dist/{structured-types.d.ts → cjs/structured-types.d.ts} +0 -0
  65. /package/dist/{structured-types.js → cjs/structured-types.js} +0 -0
@@ -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
+ }
@@ -0,0 +1,207 @@
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
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as crypto from 'crypto';
10
+ // ─── Cache Key Generator ─────────────────────────────────────────────────────
11
+ function generateCacheKey(model, query, context, config) {
12
+ const data = JSON.stringify({ model, query, context, config });
13
+ return crypto.createHash('sha256').update(data).digest('hex');
14
+ }
15
+ // ─── In-Memory Cache ─────────────────────────────────────────────────────────
16
+ export class MemoryCache {
17
+ constructor(maxEntries = 1000) {
18
+ this.store = new Map();
19
+ this.maxEntries = maxEntries;
20
+ }
21
+ get(key) {
22
+ const entry = this.store.get(key);
23
+ if (!entry)
24
+ return undefined;
25
+ // Check TTL
26
+ if (Date.now() - entry.createdAt > entry.ttl * 1000) {
27
+ this.store.delete(key);
28
+ return undefined;
29
+ }
30
+ entry.hitCount++;
31
+ return entry.value;
32
+ }
33
+ set(key, value, ttl) {
34
+ // Evict oldest if at capacity
35
+ if (this.store.size >= this.maxEntries && !this.store.has(key)) {
36
+ const oldestKey = this.store.keys().next().value;
37
+ if (oldestKey !== undefined) {
38
+ this.store.delete(oldestKey);
39
+ }
40
+ }
41
+ this.store.set(key, {
42
+ key,
43
+ value,
44
+ createdAt: Date.now(),
45
+ ttl,
46
+ hitCount: 0,
47
+ });
48
+ }
49
+ has(key) {
50
+ const entry = this.store.get(key);
51
+ if (!entry)
52
+ return false;
53
+ if (Date.now() - entry.createdAt > entry.ttl * 1000) {
54
+ this.store.delete(key);
55
+ return false;
56
+ }
57
+ return true;
58
+ }
59
+ delete(key) {
60
+ return this.store.delete(key);
61
+ }
62
+ clear() {
63
+ this.store.clear();
64
+ }
65
+ size() {
66
+ // Clean expired entries
67
+ const now = Date.now();
68
+ for (const [key, entry] of this.store) {
69
+ if (now - entry.createdAt > entry.ttl * 1000) {
70
+ this.store.delete(key);
71
+ }
72
+ }
73
+ return this.store.size;
74
+ }
75
+ }
76
+ // ─── File-Based Cache ────────────────────────────────────────────────────────
77
+ export class FileCache {
78
+ constructor(cacheDir = '.rlm-cache', maxEntries = 1000) {
79
+ this.cacheDir = path.resolve(cacheDir);
80
+ this.maxEntries = maxEntries;
81
+ if (!fs.existsSync(this.cacheDir)) {
82
+ fs.mkdirSync(this.cacheDir, { recursive: true });
83
+ }
84
+ }
85
+ filePath(key) {
86
+ return path.join(this.cacheDir, `${key}.json`);
87
+ }
88
+ get(key) {
89
+ const fp = this.filePath(key);
90
+ if (!fs.existsSync(fp))
91
+ return undefined;
92
+ try {
93
+ const data = JSON.parse(fs.readFileSync(fp, 'utf-8'));
94
+ if (Date.now() - data.createdAt > data.ttl * 1000) {
95
+ fs.unlinkSync(fp);
96
+ return undefined;
97
+ }
98
+ return data.value;
99
+ }
100
+ catch (_a) {
101
+ return undefined;
102
+ }
103
+ }
104
+ set(key, value, ttl) {
105
+ const entry = {
106
+ key,
107
+ value,
108
+ createdAt: Date.now(),
109
+ ttl,
110
+ hitCount: 0,
111
+ };
112
+ try {
113
+ fs.writeFileSync(this.filePath(key), JSON.stringify(entry), 'utf-8');
114
+ }
115
+ catch (_a) {
116
+ // Silently fail on write errors
117
+ }
118
+ }
119
+ has(key) {
120
+ return this.get(key) !== undefined;
121
+ }
122
+ delete(key) {
123
+ const fp = this.filePath(key);
124
+ if (fs.existsSync(fp)) {
125
+ fs.unlinkSync(fp);
126
+ return true;
127
+ }
128
+ return false;
129
+ }
130
+ clear() {
131
+ if (fs.existsSync(this.cacheDir)) {
132
+ const files = fs.readdirSync(this.cacheDir);
133
+ for (const file of files) {
134
+ if (file.endsWith('.json')) {
135
+ fs.unlinkSync(path.join(this.cacheDir, file));
136
+ }
137
+ }
138
+ }
139
+ }
140
+ size() {
141
+ if (!fs.existsSync(this.cacheDir))
142
+ return 0;
143
+ return fs.readdirSync(this.cacheDir).filter(f => f.endsWith('.json')).length;
144
+ }
145
+ }
146
+ // ─── RLM Cache Manager ──────────────────────────────────────────────────────
147
+ export class RLMCache {
148
+ constructor(config = {}) {
149
+ var _a, _b, _c, _d, _e, _f;
150
+ this.stats = { hits: 0, misses: 0, size: 0, hitRate: 0, evictions: 0 };
151
+ this.config = {
152
+ enabled: (_a = config.enabled) !== null && _a !== void 0 ? _a : false,
153
+ strategy: (_b = config.strategy) !== null && _b !== void 0 ? _b : 'exact',
154
+ maxEntries: (_c = config.maxEntries) !== null && _c !== void 0 ? _c : 1000,
155
+ ttl: (_d = config.ttl) !== null && _d !== void 0 ? _d : 3600,
156
+ storage: (_e = config.storage) !== null && _e !== void 0 ? _e : 'memory',
157
+ cacheDir: (_f = config.cacheDir) !== null && _f !== void 0 ? _f : '.rlm-cache',
158
+ };
159
+ if (this.config.storage === 'file') {
160
+ this.provider = new FileCache(this.config.cacheDir, this.config.maxEntries);
161
+ }
162
+ else {
163
+ this.provider = new MemoryCache(this.config.maxEntries);
164
+ }
165
+ }
166
+ /** Check if caching is enabled */
167
+ get enabled() {
168
+ return this.config.enabled && this.config.strategy !== 'none';
169
+ }
170
+ /** Look up a cached result */
171
+ lookup(model, query, context, extra) {
172
+ if (!this.enabled)
173
+ return { hit: false };
174
+ const key = generateCacheKey(model, query, context, extra);
175
+ const value = this.provider.get(key);
176
+ if (value !== undefined) {
177
+ this.stats.hits++;
178
+ this.updateHitRate();
179
+ return { hit: true, value };
180
+ }
181
+ this.stats.misses++;
182
+ this.updateHitRate();
183
+ return { hit: false };
184
+ }
185
+ /** Store a result in the cache */
186
+ store(model, query, context, value, extra) {
187
+ if (!this.enabled)
188
+ return;
189
+ const key = generateCacheKey(model, query, context, extra);
190
+ this.provider.set(key, value, this.config.ttl);
191
+ this.stats.size = this.provider.size();
192
+ }
193
+ /** Get cache statistics */
194
+ getStats() {
195
+ this.stats.size = this.provider.size();
196
+ return Object.assign({}, this.stats);
197
+ }
198
+ /** Clear the cache */
199
+ clear() {
200
+ this.provider.clear();
201
+ this.stats = { hits: 0, misses: 0, size: 0, hitRate: 0, evictions: 0 };
202
+ }
203
+ updateHitRate() {
204
+ const total = this.stats.hits + this.stats.misses;
205
+ this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
206
+ }
207
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Configuration validation for recursive-llm-ts.
3
+ *
4
+ * Validates RLMConfig at construction time with clear error messages.
5
+ */
6
+ import { RLMConfig } from './bridge-interface';
7
+ import { CacheConfig } from './cache';
8
+ import { RetryConfig, FallbackConfig } from './retry';
9
+ export interface RLMExtendedConfig extends RLMConfig {
10
+ /** Cache configuration */
11
+ cache?: CacheConfig;
12
+ /** Retry configuration */
13
+ retry?: RetryConfig;
14
+ /** Fallback model configuration */
15
+ fallback?: FallbackConfig;
16
+ /** LiteLLM passthrough parameters */
17
+ litellm_params?: Record<string, unknown>;
18
+ }
19
+ export type ValidationLevel = 'error' | 'warning' | 'info';
20
+ export interface ValidationIssue {
21
+ level: ValidationLevel;
22
+ field: string;
23
+ message: string;
24
+ }
25
+ export interface ValidationResult {
26
+ valid: boolean;
27
+ issues: ValidationIssue[];
28
+ }
29
+ /**
30
+ * Validate an RLM configuration.
31
+ * Returns issues rather than throwing, allowing callers to handle gracefully.
32
+ */
33
+ export declare function validateConfig(config: RLMExtendedConfig): ValidationResult;
34
+ /**
35
+ * Validate config and throw on errors. Logs warnings.
36
+ */
37
+ export declare function assertValidConfig(config: RLMExtendedConfig): void;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Configuration validation for recursive-llm-ts.
3
+ *
4
+ * Validates RLMConfig at construction time with clear error messages.
5
+ */
6
+ import { RLMConfigError } from './errors.js';
7
+ // ─── Known Config Keys ───────────────────────────────────────────────────────
8
+ const KNOWN_CONFIG_KEYS = new Set([
9
+ 'recursive_model',
10
+ 'api_base',
11
+ 'api_key',
12
+ 'max_depth',
13
+ 'max_iterations',
14
+ 'go_binary_path',
15
+ 'meta_agent',
16
+ 'observability',
17
+ 'debug',
18
+ 'cache',
19
+ 'retry',
20
+ 'fallback',
21
+ 'litellm_params',
22
+ // Legacy LiteLLM passthrough keys (commonly used)
23
+ 'api_version',
24
+ 'timeout',
25
+ 'temperature',
26
+ 'max_tokens',
27
+ ]);
28
+ // ─── Config Validator ────────────────────────────────────────────────────────
29
+ /**
30
+ * Validate an RLM configuration.
31
+ * Returns issues rather than throwing, allowing callers to handle gracefully.
32
+ */
33
+ export function validateConfig(config) {
34
+ const issues = [];
35
+ // Check for unknown keys (likely typos)
36
+ for (const key of Object.keys(config)) {
37
+ if (!KNOWN_CONFIG_KEYS.has(key)) {
38
+ issues.push({
39
+ level: 'warning',
40
+ field: key,
41
+ message: `Unknown config key "${key}". This may be a typo. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(', ')}`,
42
+ });
43
+ }
44
+ }
45
+ // Validate numeric fields
46
+ if (config.max_depth !== undefined) {
47
+ if (typeof config.max_depth !== 'number' || config.max_depth < 1) {
48
+ issues.push({ level: 'error', field: 'max_depth', message: 'max_depth must be a positive integer' });
49
+ }
50
+ }
51
+ if (config.max_iterations !== undefined) {
52
+ if (typeof config.max_iterations !== 'number' || config.max_iterations < 1) {
53
+ issues.push({ level: 'error', field: 'max_iterations', message: 'max_iterations must be a positive integer' });
54
+ }
55
+ }
56
+ // Validate API base URL
57
+ if (config.api_base !== undefined && typeof config.api_base === 'string') {
58
+ try {
59
+ new URL(config.api_base);
60
+ }
61
+ catch (_a) {
62
+ issues.push({ level: 'error', field: 'api_base', message: `api_base "${config.api_base}" is not a valid URL` });
63
+ }
64
+ }
65
+ // Validate meta_agent config
66
+ if (config.meta_agent) {
67
+ if (typeof config.meta_agent.enabled !== 'boolean') {
68
+ issues.push({ level: 'error', field: 'meta_agent.enabled', message: 'meta_agent.enabled must be a boolean' });
69
+ }
70
+ if (config.meta_agent.max_optimize_len !== undefined) {
71
+ if (typeof config.meta_agent.max_optimize_len !== 'number' || config.meta_agent.max_optimize_len < 0) {
72
+ issues.push({ level: 'error', field: 'meta_agent.max_optimize_len', message: 'max_optimize_len must be a non-negative number' });
73
+ }
74
+ }
75
+ }
76
+ // Validate observability config
77
+ if (config.observability) {
78
+ const obs = config.observability;
79
+ if (obs.trace_enabled && !obs.trace_endpoint) {
80
+ issues.push({
81
+ level: 'warning',
82
+ field: 'observability.trace_endpoint',
83
+ message: 'trace_enabled is true but no trace_endpoint is configured. Traces will not be exported.',
84
+ });
85
+ }
86
+ if (obs.langfuse_enabled) {
87
+ if (!obs.langfuse_public_key && !process.env.LANGFUSE_PUBLIC_KEY) {
88
+ issues.push({
89
+ level: 'warning',
90
+ field: 'observability.langfuse_public_key',
91
+ message: 'langfuse_enabled is true but no public key is set (config or LANGFUSE_PUBLIC_KEY env var).',
92
+ });
93
+ }
94
+ if (!obs.langfuse_secret_key && !process.env.LANGFUSE_SECRET_KEY) {
95
+ issues.push({
96
+ level: 'warning',
97
+ field: 'observability.langfuse_secret_key',
98
+ message: 'langfuse_enabled is true but no secret key is set (config or LANGFUSE_SECRET_KEY env var).',
99
+ });
100
+ }
101
+ }
102
+ }
103
+ // Validate cache config
104
+ if (config.cache) {
105
+ if (config.cache.maxEntries !== undefined && (typeof config.cache.maxEntries !== 'number' || config.cache.maxEntries < 1)) {
106
+ issues.push({ level: 'error', field: 'cache.maxEntries', message: 'cache.maxEntries must be a positive integer' });
107
+ }
108
+ if (config.cache.ttl !== undefined && (typeof config.cache.ttl !== 'number' || config.cache.ttl < 0)) {
109
+ issues.push({ level: 'error', field: 'cache.ttl', message: 'cache.ttl must be a non-negative number (seconds)' });
110
+ }
111
+ }
112
+ // Validate retry config
113
+ if (config.retry) {
114
+ if (config.retry.maxRetries !== undefined && (typeof config.retry.maxRetries !== 'number' || config.retry.maxRetries < 0)) {
115
+ issues.push({ level: 'error', field: 'retry.maxRetries', message: 'retry.maxRetries must be a non-negative integer' });
116
+ }
117
+ if (config.retry.baseDelay !== undefined && (typeof config.retry.baseDelay !== 'number' || config.retry.baseDelay < 0)) {
118
+ issues.push({ level: 'error', field: 'retry.baseDelay', message: 'retry.baseDelay must be a non-negative number (ms)' });
119
+ }
120
+ }
121
+ // Check for missing API key
122
+ if (!config.api_key && !process.env.OPENAI_API_KEY) {
123
+ issues.push({
124
+ level: 'info',
125
+ field: 'api_key',
126
+ message: 'No API key configured (api_key or OPENAI_API_KEY env var). Ensure it is set before making completions.',
127
+ });
128
+ }
129
+ return {
130
+ valid: issues.filter(i => i.level === 'error').length === 0,
131
+ issues,
132
+ };
133
+ }
134
+ /**
135
+ * Validate config and throw on errors. Logs warnings.
136
+ */
137
+ export function assertValidConfig(config) {
138
+ const result = validateConfig(config);
139
+ for (const issue of result.issues) {
140
+ if (issue.level === 'warning') {
141
+ console.warn(`[recursive-llm-ts] Warning: ${issue.message}`);
142
+ }
143
+ }
144
+ const errors = result.issues.filter(i => i.level === 'error');
145
+ if (errors.length > 0) {
146
+ throw new RLMConfigError({
147
+ message: `Invalid RLM config: ${errors.map(e => e.message).join('; ')}`,
148
+ field: errors[0].field,
149
+ value: config[errors[0].field],
150
+ });
151
+ }
152
+ }
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ import { RLMConfig } from './bridge-interface';
3
+ import { BridgeType } from './bridge-factory';
4
+ import { StructuredRLMResult, CoordinatorConfig } from './structured-types';
5
+ export declare class RLMAgentCoordinator {
6
+ private rlm;
7
+ private config;
8
+ constructor(model: string, rlmConfig?: RLMConfig, bridgeType?: BridgeType, coordinatorConfig?: CoordinatorConfig);
9
+ /**
10
+ * Process a complex query with structured output using schema decomposition
11
+ */
12
+ processComplex<T>(query: string, context: string, schema: z.ZodSchema<T>): Promise<StructuredRLMResult<T>>;
13
+ /**
14
+ * Clean up resources
15
+ */
16
+ cleanup(): Promise<void>;
17
+ }
@@ -0,0 +1,41 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { RLM } from './rlm.js';
11
+ export class RLMAgentCoordinator {
12
+ constructor(model, rlmConfig = {}, bridgeType = 'go', coordinatorConfig = {}) {
13
+ var _a, _b, _c;
14
+ this.rlm = new RLM(model, rlmConfig, bridgeType);
15
+ this.config = {
16
+ parallelExecution: (_a = coordinatorConfig.parallelExecution) !== null && _a !== void 0 ? _a : true,
17
+ maxRetries: (_b = coordinatorConfig.maxRetries) !== null && _b !== void 0 ? _b : 3,
18
+ progressiveValidation: (_c = coordinatorConfig.progressiveValidation) !== null && _c !== void 0 ? _c : true
19
+ };
20
+ }
21
+ /**
22
+ * Process a complex query with structured output using schema decomposition
23
+ */
24
+ processComplex(query, context, schema) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ // Delegate to RLM which now handles everything in Go
27
+ return this.rlm.structuredCompletion(query, context, schema, {
28
+ maxRetries: this.config.maxRetries,
29
+ parallelExecution: this.config.parallelExecution
30
+ });
31
+ });
32
+ }
33
+ /**
34
+ * Clean up resources
35
+ */
36
+ cleanup() {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ yield this.rlm.cleanup();
39
+ });
40
+ }
41
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Structured error hierarchy for recursive-llm-ts.
3
+ *
4
+ * All library errors extend {@link RLMError}, which adds:
5
+ * - `code` – machine-readable error identifier
6
+ * - `retryable` – whether the caller should retry
7
+ * - `suggestion` – human-readable remediation hint
8
+ */
9
+ export declare class RLMError extends Error {
10
+ /** Machine-readable error code (e.g. "RATE_LIMIT", "VALIDATION") */
11
+ readonly code: string;
12
+ /** Whether this error is likely to succeed on retry */
13
+ readonly retryable: boolean;
14
+ /** Human-readable suggestion for resolving the error */
15
+ readonly suggestion?: string;
16
+ constructor(message: string, opts: {
17
+ code: string;
18
+ retryable?: boolean;
19
+ suggestion?: string;
20
+ });
21
+ }
22
+ /** Thrown when a structured output fails schema validation. */
23
+ export declare class RLMValidationError extends RLMError {
24
+ readonly expected: unknown;
25
+ readonly received: unknown;
26
+ readonly zodErrors?: unknown;
27
+ constructor(opts: {
28
+ message: string;
29
+ expected: unknown;
30
+ received: unknown;
31
+ zodErrors?: unknown;
32
+ });
33
+ }
34
+ /** Thrown when the LLM provider returns a 429 rate limit response. */
35
+ export declare class RLMRateLimitError extends RLMError {
36
+ readonly retryAfter?: number;
37
+ constructor(opts: {
38
+ message: string;
39
+ retryAfter?: number;
40
+ });
41
+ }
42
+ /** Thrown when an operation exceeds its time limit. */
43
+ export declare class RLMTimeoutError extends RLMError {
44
+ readonly elapsed: number;
45
+ readonly limit: number;
46
+ constructor(opts: {
47
+ message: string;
48
+ elapsed: number;
49
+ limit: number;
50
+ });
51
+ }
52
+ /** Thrown when the LLM provider returns an HTTP error. */
53
+ export declare class RLMProviderError extends RLMError {
54
+ readonly statusCode: number;
55
+ readonly provider: string;
56
+ readonly responseBody?: string;
57
+ constructor(opts: {
58
+ message: string;
59
+ statusCode: number;
60
+ provider: string;
61
+ responseBody?: string;
62
+ });
63
+ }
64
+ /** Thrown when the Go binary cannot be found or fails to start. */
65
+ export declare class RLMBinaryError extends RLMError {
66
+ readonly binaryPath: string;
67
+ constructor(opts: {
68
+ message: string;
69
+ binaryPath: string;
70
+ });
71
+ }
72
+ /** Thrown when the RLM configuration is invalid. */
73
+ export declare class RLMConfigError extends RLMError {
74
+ readonly field: string;
75
+ readonly value: unknown;
76
+ constructor(opts: {
77
+ message: string;
78
+ field: string;
79
+ value: unknown;
80
+ });
81
+ }
82
+ /** Thrown when a JSON Schema is malformed or unsupported. */
83
+ export declare class RLMSchemaError extends RLMError {
84
+ readonly path: string;
85
+ readonly constraint: string;
86
+ constructor(opts: {
87
+ message: string;
88
+ path: string;
89
+ constraint: string;
90
+ });
91
+ }
92
+ /** Thrown when the request exceeds the model's context window. */
93
+ export declare class RLMContextOverflowError extends RLMError {
94
+ readonly modelLimit: number;
95
+ readonly requestTokens: number;
96
+ constructor(opts: {
97
+ message: string;
98
+ modelLimit: number;
99
+ requestTokens: number;
100
+ });
101
+ }
102
+ /** Thrown when an operation is aborted via AbortController. */
103
+ export declare class RLMAbortError extends RLMError {
104
+ constructor(message?: string);
105
+ }
106
+ /**
107
+ * Classify a raw Error into the appropriate RLM error type.
108
+ * Used internally by the bridge layer to wrap Go binary errors.
109
+ */
110
+ export declare function classifyError(err: Error | string, context?: {
111
+ binaryPath?: string;
112
+ provider?: string;
113
+ }): RLMError;