recursive-llm-ts 2.0.11 → 3.0.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 CHANGED
@@ -1,6 +1,17 @@
1
1
  # recursive-llm-ts
2
2
 
3
- TypeScript bridge for [recursive-llm](https://github.com/grigori-gvadzabia/recursive-llm): Recursive Language Models for unbounded context processing.
3
+ TypeScript/JavaScript package for [Recursive Language Models (RLM)](https://github.com/alexzhang13/rlm) - process unbounded context lengths with LLMs.
4
+
5
+ **Based on the paper**: [Recursive Language Models](https://alexzhang13.github.io/blog/2025/rlm/) by Alex Zhang and Omar Khattab (MIT, 2025)
6
+
7
+ ## Features
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
4
15
 
5
16
  ## Installation
6
17
 
@@ -10,27 +21,31 @@ npm install recursive-llm-ts
10
21
 
11
22
  ### Prerequisites
12
23
 
13
- - **Runtime:** Node.js **or** Bun (both supported with automatic detection)
14
- - **Python 3.9+** - Required for the underlying recursive-llm Python package
15
- - **pip** - Python package manager
24
+ - **Node.js 16+** or **Bun 1.0+**
25
+ - **Go 1.21+** (for building from source during install)
16
26
 
17
- ### Python Dependencies
27
+ > **Note**: The package includes pre-built binaries for common platforms. Go is only needed if building from source.
18
28
 
19
- Python dependencies are **automatically installed** via the `postinstall` script when you run `npm install` or `bun install`. The script will install `litellm`, `RestrictedPython`, and other required Python packages.
29
+ ### Go Binary (Automatic)
20
30
 
21
- If automatic installation fails (e.g., pip not in PATH), you can manually install:
31
+ The `postinstall` script automatically builds the Go binary during installation. If Go is not available, the script will warn but not fail.
32
+
33
+ If you need to build manually:
22
34
 
23
35
  ```bash
24
- cd node_modules/recursive-llm-ts/recursive-llm
25
- pip install -e .
36
+ # From the package directory
37
+ cd node_modules/recursive-llm-ts
38
+ node scripts/build-go-binary.js
39
+
40
+ # Or directly with Go
41
+ cd go && go build -o ../bin/rlm-go ./cmd/rlm
26
42
  ```
27
43
 
28
- #### For Bun Users
29
- Bunpy is included as a dependency, so no additional installation needed.
44
+ Override the binary path if needed:
30
45
 
31
- The package will automatically detect your runtime and use the appropriate Python bridge:
32
- - **Node.js** → uses `pythonia` (included)
33
- - **Bun** → uses `bunpy` (peer dependency)
46
+ ```bash
47
+ export RLM_GO_BINARY=/custom/path/to/rlm-go
48
+ ```
34
49
 
35
50
  ## Usage
36
51
 
@@ -56,24 +71,28 @@ console.log(result.result);
56
71
  console.log('Stats:', result.stats);
57
72
  ```
58
73
 
59
- ### Explicit Bridge Selection
74
+ ### Bridge Selection
60
75
 
61
- If you need to explicitly specify which bridge to use:
76
+ The package automatically uses the Go binary by default (if available). You can explicitly specify a bridge if needed:
62
77
 
63
78
  ```typescript
64
79
  import { RLM } from 'recursive-llm-ts';
65
80
 
66
- // Force use of bunpy (for Bun)
81
+ // Default: Auto-detection (prefers Go if available)
67
82
  const rlm = new RLM('gpt-4o-mini', {
68
83
  max_iterations: 15,
69
84
  api_key: process.env.OPENAI_API_KEY
70
- }, 'bunpy');
85
+ });
71
86
 
72
- // Or force use of pythonia (for Node.js)
73
- const rlm2 = new RLM('gpt-4o-mini', {}, 'pythonia');
87
+ // Explicit: Force Go binary
88
+ const rlmGo = new RLM('gpt-4o-mini', {
89
+ max_iterations: 15,
90
+ api_key: process.env.OPENAI_API_KEY
91
+ }, 'go');
74
92
 
75
- // Auto-detection (default)
76
- const rlm3 = new RLM('gpt-4o-mini', {}, 'auto');
93
+ // Legacy: Use Python bridges (bunpy for Bun, pythonia for Node)
94
+ // Note: Requires separate Python dependencies
95
+ const rlmPython = new RLM('gpt-4o-mini', {}, 'bunpy');
77
96
  ```
78
97
 
79
98
 
@@ -106,7 +125,7 @@ Process a query with the given context using recursive language models.
106
125
 
107
126
  #### `cleanup(): Promise<void>`
108
127
 
109
- Clean up the Python bridge and free resources.
128
+ Clean up the bridge and free resources.
110
129
 
111
130
  ```typescript
112
131
  await rlm.cleanup();
@@ -127,6 +146,7 @@ interface RLMConfig {
127
146
  max_depth?: number; // Maximum recursion depth (default: 5)
128
147
  max_iterations?: number; // Maximum REPL iterations per call (default: 30)
129
148
  pythonia_timeout?: number; // Python bridge timeout in ms (default: 100000ms = 100s)
149
+ go_binary_path?: string; // Override path for Go binary (optional)
130
150
 
131
151
  // LiteLLM parameters - pass any additional parameters supported by LiteLLM
132
152
  api_version?: string; // API version (e.g., for Azure)
@@ -166,40 +186,37 @@ const rlm = new RLM('gpt-4o-mini', {
166
186
 
167
187
  ## Custom Providers
168
188
 
169
- This package uses [LiteLLM](https://github.com/BerriAI/litellm) under the hood, which supports **100+ LLM providers** including OpenAI, Anthropic, AWS Bedrock, Azure, Cohere, and more.
189
+ The Go binary uses an **OpenAI-compatible chat completion API** and works seamlessly with
190
+ [LiteLLM proxy](https://docs.litellm.ai/docs/simple_proxy) or any provider that supports the
191
+ OpenAI `/chat/completions` schema. This keeps the implementation provider-agnostic.
170
192
 
171
193
  ### Quick Reference
172
194
 
173
- | Provider | Model Format | Required Config |
174
- |----------|-------------|----------------|
175
- | OpenAI | `gpt-4o`, `gpt-4o-mini` | `api_key` |
176
- | Anthropic | `claude-3-5-sonnet-20241022` | `api_key` |
177
- | AWS Bedrock | `bedrock/anthropic.claude-3-sonnet...` | AWS env vars |
178
- | Azure OpenAI | `azure/gpt-4o` | `api_base`, `api_key`, `api_version` |
179
- | Ollama | `ollama/llama3.2` | `api_base` (optional) |
180
- | Custom | `openai/your-model` | `api_base`, `api_key` |
195
+ The Go binary speaks the **OpenAI chat completion schema**, so you can:
196
+
197
+ - Use OpenAI directly with `api_key`
198
+ - Use an OpenAI-compatible endpoint (Azure OpenAI, vLLM, Ollama)
199
+ - Use a LiteLLM proxy to reach providers like Anthropic, Bedrock, or Cohere
181
200
 
182
- ### Amazon Bedrock
201
+ ### Amazon Bedrock (via LiteLLM proxy)
183
202
 
184
203
  ```typescript
185
204
  import { RLM } from 'recursive-llm-ts';
186
205
 
187
206
  const rlm = new RLM('bedrock/anthropic.claude-3-sonnet-20240229-v1:0', {
188
- api_key: process.env.AWS_ACCESS_KEY_ID,
207
+ api_base: 'http://localhost:4000', // LiteLLM proxy URL
208
+ api_key: process.env.LITELLM_API_KEY,
189
209
  max_iterations: 15
190
210
  });
191
-
192
- // Set AWS credentials via environment variables:
193
- // AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_NAME
194
211
  ```
195
212
 
196
213
  ### Azure OpenAI
197
214
 
198
215
  ```typescript
199
- const rlm = new RLM('azure/gpt-4o', {
200
- api_base: 'https://your-resource.openai.azure.com',
216
+ const rlm = new RLM('gpt-4o', {
217
+ api_base: 'https://your-resource.openai.azure.com/openai/deployments/your-deployment',
201
218
  api_key: process.env.AZURE_API_KEY,
202
- api_version: '2024-02-15-preview' // Pass any LiteLLM params
219
+ api_version: '2024-02-15-preview' // Passed through to the OpenAI-compatible API
203
220
  });
204
221
  ```
205
222
 
@@ -238,14 +255,14 @@ See the [LiteLLM documentation](https://docs.litellm.ai/docs/providers) for the
238
255
 
239
256
  ## How It Works
240
257
 
241
- This package provides a TypeScript wrapper around the Python `recursive-llm` package, enabling seamless integration into Node.js/TypeScript applications. It uses [JSPyBridge (pythonia)](https://github.com/extremeheat/JSPyBridge) to provide direct Python interop - Python is bundled and runs in-process, so no external Python installation is needed.
258
+ This package provides a TypeScript wrapper around a Go implementation of Recursive-LLM, enabling seamless integration into Node.js/TypeScript applications without Python dependencies. The Go binary is built locally (or supplied via `RLM_GO_BINARY`) and invoked for completions.
242
259
 
243
260
  The recursive-llm approach breaks down large contexts into manageable chunks and processes them recursively, allowing you to work with documents of any size without hitting token limits.
244
261
 
245
262
  ### Key Features
246
263
 
247
- - ✅ **Zero Python setup** - Python runtime bundled via JSPyBridge
248
- - ✅ **Direct interop** - Native Python-JavaScript bridge (no JSON serialization)
264
+ - ✅ **No Python dependency** - Go binary handles the full recursive loop
265
+ - ✅ **Provider-agnostic** - Works with OpenAI-compatible APIs or LiteLLM proxy
249
266
  - ✅ **Type-safe** - Full TypeScript type definitions
250
267
  - ✅ **Simple API** - Just `npm install` and start using
251
268
 
package/bin/rlm-go ADDED
Binary file
@@ -1,5 +1,5 @@
1
1
  import { PythonBridge } from './bridge-interface';
2
- export type BridgeType = 'pythonia' | 'bunpy' | 'auto';
2
+ export type BridgeType = 'go' | 'pythonia' | 'bunpy' | 'auto';
3
3
  /**
4
4
  * Create appropriate Python bridge based on runtime or explicit choice
5
5
  */
@@ -43,6 +43,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
43
43
  };
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.createBridge = createBridge;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const DEFAULT_GO_BINARY = process.platform === 'win32' ? 'rlm-go.exe' : 'rlm-go';
49
+ function resolveDefaultGoBinary() {
50
+ return path.join(__dirname, '..', 'bin', DEFAULT_GO_BINARY);
51
+ }
52
+ function isGoBinaryAvailable() {
53
+ const envPath = process.env.RLM_GO_BINARY;
54
+ if (envPath && fs.existsSync(envPath)) {
55
+ return true;
56
+ }
57
+ return fs.existsSync(resolveDefaultGoBinary());
58
+ }
46
59
  /**
47
60
  * Detect the current JavaScript runtime
48
61
  */
@@ -62,42 +75,59 @@ function detectRuntime() {
62
75
  */
63
76
  function createBridge() {
64
77
  return __awaiter(this, arguments, void 0, function* (bridgeType = 'auto') {
65
- var _a;
66
78
  let selectedBridge;
67
79
  if (bridgeType === 'auto') {
68
- const runtime = detectRuntime();
69
- if (runtime === 'bun') {
70
- selectedBridge = 'bunpy';
71
- }
72
- else if (runtime === 'node') {
73
- selectedBridge = 'pythonia';
80
+ if (isGoBinaryAvailable()) {
81
+ selectedBridge = 'go';
74
82
  }
75
83
  else {
76
- throw new Error('Unable to detect runtime. Please explicitly specify bridge type.\n' +
77
- 'Supported runtimes: Node.js (pythonia) or Bun (bunpy)');
84
+ const runtime = detectRuntime();
85
+ if (runtime === 'bun') {
86
+ selectedBridge = 'bunpy';
87
+ }
88
+ else if (runtime === 'node') {
89
+ selectedBridge = 'pythonia';
90
+ }
91
+ else {
92
+ throw new Error('Unable to detect runtime. Please explicitly specify bridge type.\n' +
93
+ 'Supported runtimes: Go binary, Node.js (pythonia), or Bun (bunpy)');
94
+ }
78
95
  }
79
96
  }
80
97
  else {
81
98
  selectedBridge = bridgeType;
82
99
  }
100
+ if (selectedBridge === 'go') {
101
+ const { GoBridge } = yield Promise.resolve().then(() => __importStar(require('./go-bridge')));
102
+ return new GoBridge();
103
+ }
83
104
  if (selectedBridge === 'bunpy') {
84
105
  try {
85
106
  const { BunpyBridge } = yield Promise.resolve().then(() => __importStar(require('./bunpy-bridge')));
86
107
  return new BunpyBridge();
87
108
  }
88
109
  catch (error) {
89
- if (bridgeType === 'auto' && ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('bunpy is not installed'))) {
90
- console.warn('[recursive-llm-ts] bunpy not found, falling back to pythonia');
110
+ const errorMsg = (error === null || error === void 0 ? void 0 : error.code) === 'MODULE_NOT_FOUND'
111
+ ? 'bunpy bridge not available (Python dependencies removed in v3.0)'
112
+ : error.message;
113
+ if (bridgeType === 'auto') {
114
+ console.warn(`[recursive-llm-ts] ${errorMsg}, falling back to pythonia`);
91
115
  selectedBridge = 'pythonia';
92
116
  }
93
117
  else {
94
- throw error;
118
+ throw new Error(`${errorMsg}. Use 'go' bridge instead (default in v3.0).`);
95
119
  }
96
120
  }
97
121
  }
98
122
  if (selectedBridge === 'pythonia') {
99
- const { PythoniaBridge } = yield Promise.resolve().then(() => __importStar(require('./rlm-bridge')));
100
- return new PythoniaBridge();
123
+ try {
124
+ const { PythoniaBridge } = yield Promise.resolve().then(() => __importStar(require('./rlm-bridge')));
125
+ return new PythoniaBridge();
126
+ }
127
+ catch (error) {
128
+ throw new Error('pythonia bridge not available (Python dependencies removed in v3.0). ' +
129
+ 'Use the Go bridge instead (default) or install bunpy/pythonia separately.');
130
+ }
101
131
  }
102
132
  throw new Error('Failed to initialize bridge');
103
133
  });
@@ -14,6 +14,7 @@ export interface RLMConfig {
14
14
  max_depth?: number;
15
15
  max_iterations?: number;
16
16
  pythonia_timeout?: number;
17
+ go_binary_path?: string;
17
18
  [key: string]: any;
18
19
  }
19
20
  export interface PythonBridge {
@@ -1,8 +1,7 @@
1
1
  import { PythonBridge, RLMConfig, RLMResult } from './bridge-interface';
2
2
  export declare class BunpyBridge implements PythonBridge {
3
- private rlmModule;
4
- private python;
5
- private ensureRLMModule;
6
- completion(model: string, query: string, context: string, rlmConfig?: RLMConfig): Promise<RLMResult>;
3
+ constructor();
4
+ initialize(_model: string, _config: RLMConfig): Promise<void>;
5
+ completion(_query: string, _context: string): Promise<RLMResult>;
7
6
  cleanup(): Promise<void>;
8
7
  }
@@ -1,37 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
2
+ // Stub file for bunpy bridge (removed in v3.0)
3
+ // Python dependencies are no longer included by default
4
+ // To use bunpy bridge, install: npm install bunpy
35
5
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
6
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
7
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -41,128 +11,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
41
11
  step((generator = generator.apply(thisArg, _arguments || [])).next());
42
12
  });
43
13
  };
44
- var __rest = (this && this.__rest) || function (s, e) {
45
- var t = {};
46
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
47
- t[p] = s[p];
48
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
49
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
50
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
51
- t[p[i]] = s[p[i]];
52
- }
53
- return t;
54
- };
55
14
  Object.defineProperty(exports, "__esModule", { value: true });
56
15
  exports.BunpyBridge = void 0;
57
- const path = __importStar(require("path"));
58
16
  class BunpyBridge {
59
17
  constructor() {
60
- this.rlmModule = null;
61
- this.python = null;
18
+ throw new Error('bunpy bridge is not available (Python dependencies removed in v3.0). ' +
19
+ 'Please use the Go bridge (default) or install bunpy separately: npm install bunpy');
62
20
  }
63
- ensureRLMModule() {
21
+ initialize(_model, _config) {
64
22
  return __awaiter(this, void 0, void 0, function* () {
65
- var _a;
66
- if (this.rlmModule)
67
- return;
68
- // Lazy load bunpy to avoid errors in Node.js environments
69
- try {
70
- // Dynamic import to avoid TypeScript errors when bunpy is not installed
71
- const bunpy = yield new Function('return import("bunpy")')();
72
- this.python = bunpy.python;
73
- }
74
- catch (error) {
75
- throw new Error('bunpy is not installed. Install it with: bun add bunpy\n' +
76
- 'Note: bunpy only works with Bun runtime, not Node.js');
77
- }
78
- // Import sys module to add path
79
- const sys = this.python.import('sys');
80
- const pythonExecutable = (() => {
81
- try {
82
- const sysExecutable = sys.executable;
83
- if (sysExecutable && typeof sysExecutable.valueOf === 'function') {
84
- const value = sysExecutable.valueOf();
85
- if (typeof value === 'string' && value.trim()) {
86
- return value;
87
- }
88
- }
89
- if (typeof sysExecutable === 'string' && sysExecutable.trim()) {
90
- return sysExecutable;
91
- }
92
- }
93
- catch (_a) {
94
- // Fall back if bunpy can't coerce sys.executable
95
- }
96
- return 'python';
97
- })();
98
- const pythonCmd = pythonExecutable.includes(' ') ? `"${pythonExecutable}"` : pythonExecutable;
99
- const pythonPackagePath = path.join(__dirname, '..', 'recursive-llm');
100
- const pythonSrcPath = path.join(pythonPackagePath, 'src');
101
- const pipCmd = `${pythonCmd} -m pip install -e "${pythonPackagePath}"`;
102
- sys.path.insert(0, pythonSrcPath);
103
- // Try to import rlm, install deps if import fails
104
- try {
105
- this.rlmModule = this.python.import('rlm');
106
- }
107
- catch (error) {
108
- // If import fails, try installing dependencies
109
- if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('No module named')) {
110
- console.log('[recursive-llm-ts] Installing Python dependencies (first time only)...');
111
- try {
112
- const { execSync } = yield Promise.resolve().then(() => __importStar(require('child_process')));
113
- execSync(pipCmd, { stdio: 'inherit' });
114
- console.log('[recursive-llm-ts] ✓ Python dependencies installed');
115
- // Try import again
116
- this.rlmModule = this.python.import('rlm');
117
- }
118
- catch (installError) {
119
- throw new Error('Failed to import rlm module after installing dependencies.\n' +
120
- `Manual installation: ${pipCmd}\n` +
121
- `Error: ${installError.message || installError}`);
122
- }
123
- }
124
- else {
125
- throw new Error('Failed to import rlm module.\n' +
126
- `Run: ${pipCmd}\n` +
127
- `Original error: ${error.message || error}`);
128
- }
129
- }
23
+ throw new Error('bunpy bridge not available');
130
24
  });
131
25
  }
132
- completion(model_1, query_1, context_1) {
133
- return __awaiter(this, arguments, void 0, function* (model, query, context, rlmConfig = {}) {
134
- yield this.ensureRLMModule();
135
- try {
136
- // Remove pythonia_timeout from config (not applicable to bunpy)
137
- const { pythonia_timeout } = rlmConfig, pythonConfig = __rest(rlmConfig, ["pythonia_timeout"]);
138
- // Create RLM instance with config
139
- const RLMClass = this.rlmModule.RLM;
140
- const rlmInstance = RLMClass(model, pythonConfig);
141
- // Call completion method
142
- const result = rlmInstance.completion(query, context);
143
- const stats = rlmInstance.stats;
144
- // Convert Python stats dict to JS object
145
- const statsObj = {
146
- llm_calls: stats.llm_calls,
147
- iterations: stats.iterations,
148
- depth: stats.depth
149
- };
150
- return {
151
- result: String(result),
152
- stats: statsObj
153
- };
154
- }
155
- catch (error) {
156
- console.error('[RLM_DEBUG] Error details:', error);
157
- throw new Error(`RLM completion failed: ${error.message || error}`);
158
- }
26
+ completion(_query, _context) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ throw new Error('bunpy bridge not available');
159
29
  });
160
30
  }
161
31
  cleanup() {
162
32
  return __awaiter(this, void 0, void 0, function* () {
163
- // Bunpy doesn't need explicit cleanup like pythonia
164
- this.rlmModule = null;
165
- this.python = null;
33
+ // No-op
166
34
  });
167
35
  }
168
36
  }
@@ -0,0 +1,5 @@
1
+ import { PythonBridge, RLMConfig, RLMResult } from './bridge-interface';
2
+ export declare class GoBridge implements PythonBridge {
3
+ completion(model: string, query: string, context: string, rlmConfig?: RLMConfig): Promise<RLMResult>;
4
+ cleanup(): Promise<void>;
5
+ }
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __rest = (this && this.__rest) || function (s, e) {
45
+ var t = {};
46
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
47
+ t[p] = s[p];
48
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
49
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
50
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
51
+ t[p[i]] = s[p[i]];
52
+ }
53
+ return t;
54
+ };
55
+ Object.defineProperty(exports, "__esModule", { value: true });
56
+ exports.GoBridge = void 0;
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ const child_process_1 = require("child_process");
60
+ const DEFAULT_BINARY_NAME = process.platform === 'win32' ? 'rlm.exe' : 'rlm';
61
+ function resolveBinaryPath(rlmConfig) {
62
+ const configuredPath = rlmConfig.go_binary_path || process.env.RLM_GO_BINARY;
63
+ if (configuredPath) {
64
+ return configuredPath;
65
+ }
66
+ // Try multiple locations
67
+ const possiblePaths = [
68
+ path.join(__dirname, '..', 'go', DEFAULT_BINARY_NAME), // Development
69
+ path.join(__dirname, '..', 'bin', DEFAULT_BINARY_NAME), // NPM package
70
+ ];
71
+ for (const p of possiblePaths) {
72
+ if (fs.existsSync(p)) {
73
+ return p;
74
+ }
75
+ }
76
+ return possiblePaths[0]; // Return first path, error will be caught later
77
+ }
78
+ function assertBinaryExists(binaryPath) {
79
+ if (!fs.existsSync(binaryPath)) {
80
+ throw new Error(`Go RLM binary not found at ${binaryPath}.\n` +
81
+ 'Build it with: node scripts/build-go-binary.js');
82
+ }
83
+ }
84
+ function sanitizeConfig(config) {
85
+ const { pythonia_timeout, go_binary_path } = config, sanitized = __rest(config, ["pythonia_timeout", "go_binary_path"]);
86
+ return sanitized;
87
+ }
88
+ class GoBridge {
89
+ completion(model_1, query_1, context_1) {
90
+ return __awaiter(this, arguments, void 0, function* (model, query, context, rlmConfig = {}) {
91
+ const binaryPath = resolveBinaryPath(rlmConfig);
92
+ assertBinaryExists(binaryPath);
93
+ const payload = JSON.stringify({
94
+ model,
95
+ query,
96
+ context,
97
+ config: sanitizeConfig(rlmConfig)
98
+ });
99
+ return new Promise((resolve, reject) => {
100
+ const child = (0, child_process_1.spawn)(binaryPath, [], { stdio: ['pipe', 'pipe', 'pipe'] });
101
+ let stdout = '';
102
+ let stderr = '';
103
+ child.stdout.on('data', (data) => {
104
+ stdout += data.toString();
105
+ });
106
+ child.stderr.on('data', (data) => {
107
+ stderr += data.toString();
108
+ });
109
+ child.on('error', (error) => {
110
+ reject(new Error(`Failed to start Go binary: ${error.message}`));
111
+ });
112
+ child.on('close', (code) => {
113
+ if (code !== 0) {
114
+ reject(new Error(stderr || `Go binary exited with code ${code}`));
115
+ return;
116
+ }
117
+ try {
118
+ const parsed = JSON.parse(stdout);
119
+ resolve(parsed);
120
+ }
121
+ catch (error) {
122
+ reject(new Error(`Failed to parse Go response: ${error.message || error}`));
123
+ }
124
+ });
125
+ child.stdin.write(payload);
126
+ child.stdin.end();
127
+ });
128
+ });
129
+ }
130
+ cleanup() {
131
+ return __awaiter(this, void 0, void 0, function* () {
132
+ // No persistent processes to clean up.
133
+ });
134
+ }
135
+ }
136
+ exports.GoBridge = GoBridge;