recursive-llm-ts 4.4.0 → 4.4.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.
- package/README.md +171 -0
- package/bin/rlm-go +0 -0
- package/dist/bridge-interface.d.ts +45 -0
- package/dist/file-storage.d.ts +122 -0
- package/dist/file-storage.js +697 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +7 -1
- package/dist/rlm-bridge.js +0 -1
- package/dist/rlm.d.ts +31 -1
- package/dist/rlm.js +52 -0
- package/go/rlm/structured.go +233 -100
- package/go/rlm/structured_test.go +895 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ TypeScript/JavaScript package for [Recursive Language Models (RLM)](https://gith
|
|
|
15
15
|
🔍 **Structured Outputs** - Extract typed data with Zod schemas and parallel execution
|
|
16
16
|
🧠 **Meta-Agent Mode** - Automatically optimize queries for better results
|
|
17
17
|
📊 **Observability** - OpenTelemetry tracing, Langfuse integration, and debug logging
|
|
18
|
+
📁 **File Storage** - Process local directories or S3/MinIO/LocalStack buckets as LLM context
|
|
18
19
|
|
|
19
20
|
## Installation
|
|
20
21
|
|
|
@@ -281,6 +282,123 @@ LANGFUSE_SECRET_KEY=sk-...
|
|
|
281
282
|
LANGFUSE_HOST=https://cloud.langfuse.com
|
|
282
283
|
```
|
|
283
284
|
|
|
285
|
+
### File Storage Context
|
|
286
|
+
|
|
287
|
+
Process files from local directories or S3-compatible storage as LLM context. Supports recursive directory traversal, filtering, and automatic context formatting.
|
|
288
|
+
|
|
289
|
+
#### Local Files
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import { RLM } from 'recursive-llm-ts';
|
|
293
|
+
|
|
294
|
+
const rlm = new RLM('gpt-4o-mini', {
|
|
295
|
+
api_key: process.env.OPENAI_API_KEY
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Process all TypeScript files in a directory
|
|
299
|
+
const result = await rlm.completionFromFiles(
|
|
300
|
+
'Summarize the architecture of this codebase',
|
|
301
|
+
{
|
|
302
|
+
type: 'local',
|
|
303
|
+
path: '/path/to/project/src',
|
|
304
|
+
extensions: ['.ts', '.tsx'],
|
|
305
|
+
excludePatterns: ['*.test.ts', '*.spec.ts'],
|
|
306
|
+
maxFileSize: 100_000, // Skip files over 100KB
|
|
307
|
+
}
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
console.log(result.result);
|
|
311
|
+
console.log(`Files processed: ${result.fileStorage?.files.length}`);
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### S3 / Object Storage
|
|
315
|
+
|
|
316
|
+
Works with AWS S3, MinIO, LocalStack, DigitalOcean Spaces, and Backblaze B2.
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// AWS S3 with explicit credentials
|
|
320
|
+
const result = await rlm.completionFromFiles(
|
|
321
|
+
'What are the key findings in these reports?',
|
|
322
|
+
{
|
|
323
|
+
type: 's3',
|
|
324
|
+
path: 'my-bucket', // Bucket name
|
|
325
|
+
prefix: 'reports/2024/', // Folder prefix
|
|
326
|
+
extensions: ['.md', '.txt'],
|
|
327
|
+
credentials: {
|
|
328
|
+
accessKeyId: 'AKIA...',
|
|
329
|
+
secretAccessKey: '...',
|
|
330
|
+
},
|
|
331
|
+
region: 'us-west-2',
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
// S3 with environment variable credentials
|
|
336
|
+
// Uses AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
|
|
337
|
+
const result2 = await rlm.completionFromFiles(
|
|
338
|
+
'Summarize these documents',
|
|
339
|
+
{ type: 's3', path: 'my-bucket', prefix: 'docs/' }
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
// MinIO / LocalStack
|
|
343
|
+
const result3 = await rlm.completionFromFiles(
|
|
344
|
+
'Analyze the data',
|
|
345
|
+
{
|
|
346
|
+
type: 's3',
|
|
347
|
+
path: 'local-bucket',
|
|
348
|
+
endpoint: 'http://localhost:9000', // MinIO
|
|
349
|
+
credentials: { accessKeyId: 'minioadmin', secretAccessKey: 'minioadmin' },
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Credential Resolution Order:**
|
|
355
|
+
1. Explicit `credentials` in config
|
|
356
|
+
2. Environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`
|
|
357
|
+
3. AWS SDK default credential chain (IAM roles, `~/.aws/credentials`, ECS task role, etc.)
|
|
358
|
+
|
|
359
|
+
#### Structured Extraction from Files
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
import { z } from 'zod';
|
|
363
|
+
|
|
364
|
+
const schema = z.object({
|
|
365
|
+
summary: z.string(),
|
|
366
|
+
mainTopics: z.array(z.string()),
|
|
367
|
+
sentiment: z.enum(['positive', 'negative', 'neutral']),
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
const result = await rlm.structuredCompletionFromFiles(
|
|
371
|
+
'Extract a summary, main topics, and overall sentiment',
|
|
372
|
+
{ type: 'local', path: './docs', extensions: ['.md'] },
|
|
373
|
+
schema
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
console.log(result.result.mainTopics); // string[]
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Preview Files Before Processing
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
import { FileContextBuilder } from 'recursive-llm-ts';
|
|
383
|
+
|
|
384
|
+
const builder = new FileContextBuilder({
|
|
385
|
+
type: 'local',
|
|
386
|
+
path: './src',
|
|
387
|
+
extensions: ['.ts'],
|
|
388
|
+
excludePatterns: ['node_modules/**'],
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// List matching files without reading content
|
|
392
|
+
const files = await builder.listMatchingFiles();
|
|
393
|
+
console.log('Would process:', files);
|
|
394
|
+
|
|
395
|
+
// Build full context
|
|
396
|
+
const ctx = await builder.buildContext();
|
|
397
|
+
console.log(`Total size: ${ctx.totalSize} bytes`);
|
|
398
|
+
console.log(`Files included: ${ctx.files.length}`);
|
|
399
|
+
console.log(`Files skipped: ${ctx.skipped.length}`);
|
|
400
|
+
```
|
|
401
|
+
|
|
284
402
|
## API
|
|
285
403
|
|
|
286
404
|
### `RLM`
|
|
@@ -330,6 +448,21 @@ const result = await rlm.structuredCompletion('Analyze', doc, schema);
|
|
|
330
448
|
// result.result is typed as { score: number, summary: string }
|
|
331
449
|
```
|
|
332
450
|
|
|
451
|
+
#### `completionFromFiles(query: string, fileConfig: FileStorageConfig): Promise<RLMResult & { fileStorage?: FileStorageResult }>`
|
|
452
|
+
|
|
453
|
+
Process a query using files from local or S3 storage as context.
|
|
454
|
+
|
|
455
|
+
**Parameters:**
|
|
456
|
+
- `query`: The question or task to perform
|
|
457
|
+
- `fileConfig`: File storage configuration (local path or S3 bucket)
|
|
458
|
+
|
|
459
|
+
**Returns:**
|
|
460
|
+
- Result with `fileStorage` metadata (files included, skipped, total size)
|
|
461
|
+
|
|
462
|
+
#### `structuredCompletionFromFiles<T>(query: string, fileConfig: FileStorageConfig, schema: ZodSchema<T>, options?): Promise<StructuredRLMResult<T> & { fileStorage?: FileStorageResult }>`
|
|
463
|
+
|
|
464
|
+
Extract structured data from file-based context.
|
|
465
|
+
|
|
333
466
|
#### `cleanup(): Promise<void>`
|
|
334
467
|
|
|
335
468
|
Clean up the bridge and free resources.
|
|
@@ -423,6 +556,33 @@ interface TraceEvent {
|
|
|
423
556
|
trace_id?: string;
|
|
424
557
|
span_id?: string;
|
|
425
558
|
}
|
|
559
|
+
|
|
560
|
+
interface FileStorageConfig {
|
|
561
|
+
type: 'local' | 's3'; // Storage provider type
|
|
562
|
+
path: string; // Local directory path or S3 bucket name
|
|
563
|
+
prefix?: string; // S3 key prefix (folder path)
|
|
564
|
+
region?: string; // AWS region (default: AWS_REGION env or 'us-east-1')
|
|
565
|
+
credentials?: { // S3 explicit credentials (optional)
|
|
566
|
+
accessKeyId: string;
|
|
567
|
+
secretAccessKey: string;
|
|
568
|
+
sessionToken?: string;
|
|
569
|
+
};
|
|
570
|
+
endpoint?: string; // Custom S3 endpoint (MinIO, LocalStack, etc.)
|
|
571
|
+
forcePathStyle?: boolean; // Force path-style S3 URLs (auto-enabled with endpoint)
|
|
572
|
+
extensions?: string[]; // File extensions to include (e.g., ['.ts', '.md'])
|
|
573
|
+
includePatterns?: string[]; // Glob patterns to include
|
|
574
|
+
excludePatterns?: string[]; // Glob patterns to exclude
|
|
575
|
+
maxFileSize?: number; // Max individual file size in bytes (default: 1MB)
|
|
576
|
+
maxTotalSize?: number; // Max total context size in bytes (default: 10MB)
|
|
577
|
+
maxFiles?: number; // Max number of files (default: 1000)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
interface FileStorageResult {
|
|
581
|
+
context: string; // Built context string with file contents
|
|
582
|
+
files: Array<{ relativePath: string; size: number }>;
|
|
583
|
+
totalSize: number;
|
|
584
|
+
skipped: Array<{ relativePath: string; reason: string }>;
|
|
585
|
+
}
|
|
426
586
|
```
|
|
427
587
|
|
|
428
588
|
## Environment Variables
|
|
@@ -441,6 +601,17 @@ const rlm = new RLM('gpt-4o-mini', {
|
|
|
441
601
|
});
|
|
442
602
|
```
|
|
443
603
|
|
|
604
|
+
### S3 File Storage
|
|
605
|
+
|
|
606
|
+
When using S3 file storage without explicit credentials, these environment variables are checked:
|
|
607
|
+
|
|
608
|
+
```bash
|
|
609
|
+
export AWS_ACCESS_KEY_ID='your-access-key'
|
|
610
|
+
export AWS_SECRET_ACCESS_KEY='your-secret-key'
|
|
611
|
+
export AWS_SESSION_TOKEN='optional-session-token'
|
|
612
|
+
export AWS_REGION='us-east-1'
|
|
613
|
+
```
|
|
614
|
+
|
|
444
615
|
## Custom Providers
|
|
445
616
|
|
|
446
617
|
The Go binary uses an **OpenAI-compatible chat completion API** and works seamlessly with
|
package/bin/rlm-go
CHANGED
|
Binary file
|
|
@@ -49,6 +49,51 @@ export interface RLMConfig {
|
|
|
49
49
|
debug?: boolean;
|
|
50
50
|
[key: string]: any;
|
|
51
51
|
}
|
|
52
|
+
export interface FileStorageConfig {
|
|
53
|
+
/** Storage type: 'local' or 's3' */
|
|
54
|
+
type: 'local' | 's3';
|
|
55
|
+
/** For local: root directory path. For S3: bucket name */
|
|
56
|
+
path: string;
|
|
57
|
+
/** For S3: the prefix (folder path) within the bucket */
|
|
58
|
+
prefix?: string;
|
|
59
|
+
/** For S3: AWS region (falls back to AWS_REGION env var, then 'us-east-1') */
|
|
60
|
+
region?: string;
|
|
61
|
+
/**
|
|
62
|
+
* For S3: explicit credentials.
|
|
63
|
+
* Resolution order:
|
|
64
|
+
* 1. This field (explicit credentials)
|
|
65
|
+
* 2. Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
|
|
66
|
+
* 3. AWS SDK default credential chain (IAM role, ~/.aws/credentials, ECS task role, etc.)
|
|
67
|
+
*/
|
|
68
|
+
credentials?: {
|
|
69
|
+
accessKeyId: string;
|
|
70
|
+
secretAccessKey: string;
|
|
71
|
+
sessionToken?: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* For S3: custom endpoint URL.
|
|
75
|
+
* Use for S3-compatible services: MinIO, LocalStack, DigitalOcean Spaces, Backblaze B2.
|
|
76
|
+
* When set, forcePathStyle is automatically enabled.
|
|
77
|
+
*/
|
|
78
|
+
endpoint?: string;
|
|
79
|
+
/**
|
|
80
|
+
* For S3: force path-style addressing (bucket in path, not subdomain).
|
|
81
|
+
* Automatically true when endpoint is set.
|
|
82
|
+
*/
|
|
83
|
+
forcePathStyle?: boolean;
|
|
84
|
+
/** Glob patterns to include (e.g. ['*.ts', '*.md']) */
|
|
85
|
+
includePatterns?: string[];
|
|
86
|
+
/** Glob patterns to exclude (e.g. ['node_modules/**']) */
|
|
87
|
+
excludePatterns?: string[];
|
|
88
|
+
/** Maximum file size in bytes to include (default: 1MB) */
|
|
89
|
+
maxFileSize?: number;
|
|
90
|
+
/** Maximum total context size in bytes (default: 10MB) */
|
|
91
|
+
maxTotalSize?: number;
|
|
92
|
+
/** Maximum number of files to include (default: 1000) */
|
|
93
|
+
maxFiles?: number;
|
|
94
|
+
/** File extensions to include (e.g. ['.ts', '.md', '.txt']) */
|
|
95
|
+
extensions?: string[];
|
|
96
|
+
}
|
|
52
97
|
export interface PythonBridge {
|
|
53
98
|
completion(model: string, query: string, context: string, rlmConfig: RLMConfig): Promise<RLMResult>;
|
|
54
99
|
cleanup(): Promise<void>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { FileStorageConfig } from './bridge-interface';
|
|
2
|
+
/**
|
|
3
|
+
* Custom error class for S3 storage operations.
|
|
4
|
+
* Provides actionable error messages for common failure modes.
|
|
5
|
+
*/
|
|
6
|
+
export declare class S3StorageError extends Error {
|
|
7
|
+
readonly code: string;
|
|
8
|
+
readonly bucket: string;
|
|
9
|
+
readonly key?: string;
|
|
10
|
+
readonly originalError?: Error;
|
|
11
|
+
constructor(opts: {
|
|
12
|
+
message: string;
|
|
13
|
+
code: string;
|
|
14
|
+
bucket: string;
|
|
15
|
+
key?: string;
|
|
16
|
+
originalError?: Error;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export { FileStorageConfig } from './bridge-interface';
|
|
20
|
+
export interface FileEntry {
|
|
21
|
+
/** Relative path from the root of the storage source */
|
|
22
|
+
relativePath: string;
|
|
23
|
+
/** File content as a string */
|
|
24
|
+
content: string;
|
|
25
|
+
/** Size in bytes */
|
|
26
|
+
size: number;
|
|
27
|
+
}
|
|
28
|
+
export interface FileStorageResult {
|
|
29
|
+
/** The built context string containing all file contents */
|
|
30
|
+
context: string;
|
|
31
|
+
/** List of files that were included */
|
|
32
|
+
files: Array<{
|
|
33
|
+
relativePath: string;
|
|
34
|
+
size: number;
|
|
35
|
+
}>;
|
|
36
|
+
/** Total size of all file contents */
|
|
37
|
+
totalSize: number;
|
|
38
|
+
/** Files that were skipped and why */
|
|
39
|
+
skipped: Array<{
|
|
40
|
+
relativePath: string;
|
|
41
|
+
reason: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
export interface FileStorageProvider {
|
|
45
|
+
listFiles(): Promise<string[]>;
|
|
46
|
+
readFile(relativePath: string): Promise<string>;
|
|
47
|
+
getFileSize(relativePath: string): Promise<number>;
|
|
48
|
+
}
|
|
49
|
+
export declare class LocalFileStorage implements FileStorageProvider {
|
|
50
|
+
private rootPath;
|
|
51
|
+
constructor(rootPath: string);
|
|
52
|
+
listFiles(): Promise<string[]>;
|
|
53
|
+
private walkDir;
|
|
54
|
+
readFile(relativePath: string): Promise<string>;
|
|
55
|
+
getFileSize(relativePath: string): Promise<number>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* S3FileStorage uses the AWS SDK v3 via dynamic import.
|
|
59
|
+
* If @aws-sdk/client-s3 is not installed, it throws a clear error.
|
|
60
|
+
*
|
|
61
|
+
* Supports:
|
|
62
|
+
* - AWS S3
|
|
63
|
+
* - MinIO (set endpoint to MinIO URL)
|
|
64
|
+
* - LocalStack (set endpoint to LocalStack URL, typically http://localhost:4566)
|
|
65
|
+
* - DigitalOcean Spaces, Backblaze B2, and other S3-compatible services
|
|
66
|
+
*
|
|
67
|
+
* Credential resolution order:
|
|
68
|
+
* 1. Explicit credentials in FileStorageConfig.credentials
|
|
69
|
+
* 2. Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
|
|
70
|
+
* 3. AWS SDK default credential chain (IAM role, ~/.aws/credentials, ECS task role, etc.)
|
|
71
|
+
*/
|
|
72
|
+
export declare class S3FileStorage implements FileStorageProvider {
|
|
73
|
+
private bucket;
|
|
74
|
+
private prefix;
|
|
75
|
+
private region;
|
|
76
|
+
private credentials?;
|
|
77
|
+
private endpoint?;
|
|
78
|
+
private forcePathStyle;
|
|
79
|
+
private s3Client;
|
|
80
|
+
constructor(config: FileStorageConfig);
|
|
81
|
+
/**
|
|
82
|
+
* Returns the credential source being used for debugging/logging.
|
|
83
|
+
*/
|
|
84
|
+
getCredentialSource(): string;
|
|
85
|
+
private getClient;
|
|
86
|
+
private buildKey;
|
|
87
|
+
listFiles(): Promise<string[]>;
|
|
88
|
+
readFile(relativePath: string): Promise<string>;
|
|
89
|
+
getFileSize(relativePath: string): Promise<number>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* FileContextBuilder reads files from a storage provider, applies filters,
|
|
93
|
+
* and builds a structured context string for LLM consumption.
|
|
94
|
+
*/
|
|
95
|
+
export declare class FileContextBuilder {
|
|
96
|
+
private provider;
|
|
97
|
+
private config;
|
|
98
|
+
constructor(config: FileStorageConfig);
|
|
99
|
+
private createProvider;
|
|
100
|
+
/**
|
|
101
|
+
* Build a structured context string from all matching files.
|
|
102
|
+
* Files are formatted with clear delimiters so the LLM can reference them.
|
|
103
|
+
*/
|
|
104
|
+
buildContext(): Promise<FileStorageResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Build a file tree overview for the LLM to understand the folder structure.
|
|
107
|
+
*/
|
|
108
|
+
private buildFileTree;
|
|
109
|
+
/**
|
|
110
|
+
* Format a single file's content with clear delimiters.
|
|
111
|
+
*/
|
|
112
|
+
private formatFileBlock;
|
|
113
|
+
/**
|
|
114
|
+
* Get just the list of files without reading content.
|
|
115
|
+
* Useful for previewing what would be included.
|
|
116
|
+
*/
|
|
117
|
+
listMatchingFiles(): Promise<string[]>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Convenience function to build context from a file storage config.
|
|
121
|
+
*/
|
|
122
|
+
export declare function buildFileContext(config: FileStorageConfig): Promise<FileStorageResult>;
|