recursive-llm-ts 1.0.7 → 2.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
@@ -10,18 +10,31 @@ npm install recursive-llm-ts
10
10
 
11
11
  ### Prerequisites
12
12
 
13
- - **Node.js** (not Bun) - This package uses `pythonia` which requires Node.js internals
13
+ - **Runtime:** Node.js **or** Bun (both supported with automatic detection)
14
14
  - **Python 3.9+** - Required for the underlying recursive-llm Python package
15
15
  - **pip** - Python package manager
16
16
 
17
17
  **Python dependencies are automatically installed** via the `postinstall` script when you `npm install`. The script will run `pip install -e` on the bundled Python package, installing `litellm`, `RestrictedPython`, and other dependencies.
18
18
 
19
+ #### For Bun Users
20
+ If using Bun, also install `bunpy`:
21
+ ```bash
22
+ bun add bunpy
23
+ ```
24
+
25
+ The package will automatically detect your runtime and use the appropriate Python bridge:
26
+ - **Node.js** → uses `pythonia` (included)
27
+ - **Bun** → uses `bunpy` (peer dependency)
28
+
19
29
  ## Usage
20
30
 
31
+ ### Automatic Runtime Detection (Recommended)
32
+
21
33
  ```typescript
22
34
  import { RLM } from 'recursive-llm-ts';
23
35
 
24
36
  // Initialize RLM with a model
37
+ // Automatically detects Node.js or Bun and uses appropriate bridge
25
38
  const rlm = new RLM('gpt-4o-mini', {
26
39
  max_iterations: 15,
27
40
  api_key: process.env.OPENAI_API_KEY
@@ -37,6 +50,26 @@ console.log(result.result);
37
50
  console.log('Stats:', result.stats);
38
51
  ```
39
52
 
53
+ ### Explicit Bridge Selection
54
+
55
+ If you need to explicitly specify which bridge to use:
56
+
57
+ ```typescript
58
+ import { RLM } from 'recursive-llm-ts';
59
+
60
+ // Force use of bunpy (for Bun)
61
+ const rlm = new RLM('gpt-4o-mini', {
62
+ max_iterations: 15,
63
+ api_key: process.env.OPENAI_API_KEY
64
+ }, 'bunpy');
65
+
66
+ // Or force use of pythonia (for Node.js)
67
+ const rlm2 = new RLM('gpt-4o-mini', {}, 'pythonia');
68
+
69
+ // Auto-detection (default)
70
+ const rlm3 = new RLM('gpt-4o-mini', {}, 'auto');
71
+ ```
72
+
40
73
 
41
74
  ## API
42
75
 
@@ -0,0 +1,6 @@
1
+ import { PythonBridge } from './bridge-interface';
2
+ export type BridgeType = 'pythonia' | 'bunpy' | 'auto';
3
+ /**
4
+ * Create appropriate Python bridge based on runtime or explicit choice
5
+ */
6
+ export declare function createBridge(bridgeType?: BridgeType): Promise<PythonBridge>;
@@ -0,0 +1,91 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.createBridge = createBridge;
46
+ /**
47
+ * Detect the current JavaScript runtime
48
+ */
49
+ function detectRuntime() {
50
+ // Check for Bun
51
+ if (typeof globalThis.Bun !== 'undefined') {
52
+ return 'bun';
53
+ }
54
+ // Check for Node.js
55
+ if (typeof process !== 'undefined' && process.versions && process.versions.node) {
56
+ return 'node';
57
+ }
58
+ return 'unknown';
59
+ }
60
+ /**
61
+ * Create appropriate Python bridge based on runtime or explicit choice
62
+ */
63
+ function createBridge() {
64
+ return __awaiter(this, arguments, void 0, function* (bridgeType = 'auto') {
65
+ let selectedBridge;
66
+ if (bridgeType === 'auto') {
67
+ const runtime = detectRuntime();
68
+ if (runtime === 'bun') {
69
+ selectedBridge = 'bunpy';
70
+ }
71
+ else if (runtime === 'node') {
72
+ selectedBridge = 'pythonia';
73
+ }
74
+ else {
75
+ throw new Error('Unable to detect runtime. Please explicitly specify bridge type.\n' +
76
+ 'Supported runtimes: Node.js (pythonia) or Bun (bunpy)');
77
+ }
78
+ }
79
+ else {
80
+ selectedBridge = bridgeType;
81
+ }
82
+ if (selectedBridge === 'bunpy') {
83
+ const { BunpyBridge } = yield Promise.resolve().then(() => __importStar(require('./bunpy-bridge')));
84
+ return new BunpyBridge();
85
+ }
86
+ else {
87
+ const { PythoniaBridge } = yield Promise.resolve().then(() => __importStar(require('./rlm-bridge')));
88
+ return new PythoniaBridge();
89
+ }
90
+ });
91
+ }
@@ -0,0 +1,22 @@
1
+ export interface RLMStats {
2
+ llm_calls: number;
3
+ iterations: number;
4
+ depth: number;
5
+ }
6
+ export interface RLMResult {
7
+ result: string;
8
+ stats: RLMStats;
9
+ }
10
+ export interface RLMConfig {
11
+ recursive_model?: string;
12
+ api_base?: string;
13
+ api_key?: string;
14
+ max_depth?: number;
15
+ max_iterations?: number;
16
+ pythonia_timeout?: number;
17
+ [key: string]: any;
18
+ }
19
+ export interface PythonBridge {
20
+ completion(model: string, query: string, context: string, rlmConfig: RLMConfig): Promise<RLMResult>;
21
+ cleanup(): Promise<void>;
22
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import { PythonBridge, RLMConfig, RLMResult } from './bridge-interface';
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>;
7
+ cleanup(): Promise<void>;
8
+ }
@@ -0,0 +1,122 @@
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.BunpyBridge = void 0;
57
+ const path = __importStar(require("path"));
58
+ class BunpyBridge {
59
+ constructor() {
60
+ this.rlmModule = null;
61
+ this.python = null;
62
+ }
63
+ ensureRLMModule() {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ if (this.rlmModule)
66
+ return;
67
+ // Lazy load bunpy to avoid errors in Node.js environments
68
+ try {
69
+ // Dynamic import to avoid TypeScript errors when bunpy is not installed
70
+ const bunpy = yield new Function('return import("bunpy")')();
71
+ this.python = bunpy.python;
72
+ }
73
+ catch (error) {
74
+ throw new Error('bunpy is not installed. Install it with: bun add bunpy\n' +
75
+ 'Note: bunpy only works with Bun runtime, not Node.js');
76
+ }
77
+ // Import sys module to add path
78
+ const sys = this.python.import('sys');
79
+ const pythonSrcPath = path.join(__dirname, '..', 'recursive-llm', 'src');
80
+ sys.path.insert(0, pythonSrcPath);
81
+ // Import the rlm module
82
+ this.rlmModule = this.python.import('rlm');
83
+ });
84
+ }
85
+ completion(model_1, query_1, context_1) {
86
+ return __awaiter(this, arguments, void 0, function* (model, query, context, rlmConfig = {}) {
87
+ yield this.ensureRLMModule();
88
+ try {
89
+ // Remove pythonia_timeout from config (not applicable to bunpy)
90
+ const { pythonia_timeout } = rlmConfig, pythonConfig = __rest(rlmConfig, ["pythonia_timeout"]);
91
+ // Create RLM instance with config
92
+ const RLMClass = this.rlmModule.RLM;
93
+ const rlmInstance = RLMClass(model, pythonConfig);
94
+ // Call completion method
95
+ const result = rlmInstance.completion(query, context);
96
+ const stats = rlmInstance.stats;
97
+ // Convert Python stats dict to JS object
98
+ const statsObj = {
99
+ llm_calls: stats.llm_calls,
100
+ iterations: stats.iterations,
101
+ depth: stats.depth
102
+ };
103
+ return {
104
+ result: String(result),
105
+ stats: statsObj
106
+ };
107
+ }
108
+ catch (error) {
109
+ console.error('[RLM_DEBUG] Error details:', error);
110
+ throw new Error(`RLM completion failed: ${error.message || error}`);
111
+ }
112
+ });
113
+ }
114
+ cleanup() {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ // Bunpy doesn't need explicit cleanup like pythonia
117
+ this.rlmModule = null;
118
+ this.python = null;
119
+ });
120
+ }
121
+ }
122
+ exports.BunpyBridge = BunpyBridge;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { RLM } from './rlm';
2
- export { RLMBridge, RLMConfig, RLMResult, RLMStats, RLMError } from './rlm-bridge';
2
+ export { RLMConfig, RLMResult, RLMStats } from './bridge-interface';
3
+ export { BridgeType } from './bridge-factory';
package/dist/index.js CHANGED
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RLMBridge = exports.RLM = void 0;
3
+ exports.RLM = void 0;
4
4
  var rlm_1 = require("./rlm");
5
5
  Object.defineProperty(exports, "RLM", { enumerable: true, get: function () { return rlm_1.RLM; } });
6
- var rlm_bridge_1 = require("./rlm-bridge");
7
- Object.defineProperty(exports, "RLMBridge", { enumerable: true, get: function () { return rlm_bridge_1.RLMBridge; } });
@@ -1,26 +1,7 @@
1
- export interface RLMStats {
2
- llm_calls: number;
3
- iterations: number;
4
- depth: number;
5
- }
6
- export interface RLMResult {
7
- result: string;
8
- stats: RLMStats;
9
- }
10
- export interface RLMError {
11
- error: string;
12
- }
13
- export interface RLMConfig {
14
- recursive_model?: string;
15
- api_base?: string;
16
- api_key?: string;
17
- max_depth?: number;
18
- max_iterations?: number;
19
- pythonia_timeout?: number;
20
- [key: string]: any;
21
- }
22
- export declare class RLMBridge {
1
+ import { PythonBridge, RLMConfig, RLMResult } from './bridge-interface';
2
+ export declare class PythoniaBridge implements PythonBridge {
23
3
  private rlmModule;
4
+ private python;
24
5
  private ensureRLMModule;
25
6
  completion(model: string, query: string, context: string, rlmConfig?: RLMConfig): Promise<RLMResult>;
26
7
  cleanup(): Promise<void>;
@@ -53,25 +53,36 @@ var __rest = (this && this.__rest) || function (s, e) {
53
53
  return t;
54
54
  };
55
55
  Object.defineProperty(exports, "__esModule", { value: true });
56
- exports.RLMBridge = void 0;
57
- const pythonia_1 = require("pythonia");
56
+ exports.PythoniaBridge = void 0;
58
57
  const path = __importStar(require("path"));
59
- class RLMBridge {
58
+ class PythoniaBridge {
60
59
  constructor() {
61
60
  this.rlmModule = null;
61
+ this.python = null;
62
62
  }
63
63
  ensureRLMModule() {
64
64
  return __awaiter(this, void 0, void 0, function* () {
65
65
  if (this.rlmModule)
66
66
  return;
67
+ // Lazy load pythonia to avoid errors in Bun environments
68
+ if (!this.python) {
69
+ try {
70
+ const pythonia = yield Promise.resolve().then(() => __importStar(require('pythonia')));
71
+ this.python = pythonia.python;
72
+ }
73
+ catch (error) {
74
+ throw new Error('pythonia is not installed. Install it with: npm install pythonia\n' +
75
+ 'Note: pythonia only works with Node.js runtime, not Bun');
76
+ }
77
+ }
67
78
  // Get path to recursive-llm Python module
68
79
  const rlmPath = path.join(__dirname, '..', 'recursive-llm', 'src', 'rlm');
69
80
  // Import sys module to add path
70
- const sys = yield (0, pythonia_1.python)('sys');
81
+ const sys = yield this.python('sys');
71
82
  const pathList = yield sys.path;
72
83
  yield pathList.insert(0, path.join(__dirname, '..', 'recursive-llm', 'src'));
73
84
  // Import the rlm module
74
- this.rlmModule = yield (0, pythonia_1.python)('rlm');
85
+ this.rlmModule = yield this.python('rlm');
75
86
  });
76
87
  }
77
88
  completion(model_1, query_1, context_1) {
@@ -107,11 +118,12 @@ class RLMBridge {
107
118
  }
108
119
  cleanup() {
109
120
  return __awaiter(this, void 0, void 0, function* () {
110
- if (this.rlmModule) {
111
- pythonia_1.python.exit();
121
+ if (this.python && this.rlmModule) {
122
+ this.python.exit();
112
123
  this.rlmModule = null;
124
+ this.python = null;
113
125
  }
114
126
  });
115
127
  }
116
128
  }
117
- exports.RLMBridge = RLMBridge;
129
+ exports.PythoniaBridge = PythoniaBridge;
package/dist/rlm.d.ts CHANGED
@@ -1,9 +1,12 @@
1
- import { RLMConfig, RLMResult } from './rlm-bridge';
1
+ import { RLMConfig, RLMResult } from './bridge-interface';
2
+ import { BridgeType } from './bridge-factory';
2
3
  export declare class RLM {
3
4
  private bridge;
4
5
  private model;
5
6
  private rlmConfig;
6
- constructor(model: string, rlmConfig?: RLMConfig);
7
+ private bridgeType;
8
+ constructor(model: string, rlmConfig?: RLMConfig, bridgeType?: BridgeType);
9
+ private ensureBridge;
7
10
  completion(query: string, context: string): Promise<RLMResult>;
8
11
  cleanup(): Promise<void>;
9
12
  }
package/dist/rlm.js CHANGED
@@ -1,18 +1,44 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.RLM = void 0;
4
- const rlm_bridge_1 = require("./rlm-bridge");
13
+ const bridge_factory_1 = require("./bridge-factory");
5
14
  class RLM {
6
- constructor(model, rlmConfig = {}) {
7
- this.bridge = new rlm_bridge_1.RLMBridge();
15
+ constructor(model, rlmConfig = {}, bridgeType = 'auto') {
16
+ this.bridge = null;
8
17
  this.model = model;
9
18
  this.rlmConfig = rlmConfig;
19
+ this.bridgeType = bridgeType;
20
+ }
21
+ ensureBridge() {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ if (!this.bridge) {
24
+ this.bridge = yield (0, bridge_factory_1.createBridge)(this.bridgeType);
25
+ }
26
+ return this.bridge;
27
+ });
10
28
  }
11
29
  completion(query, context) {
12
- return this.bridge.completion(this.model, query, context, this.rlmConfig);
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ const bridge = yield this.ensureBridge();
32
+ return bridge.completion(this.model, query, context, this.rlmConfig);
33
+ });
13
34
  }
14
35
  cleanup() {
15
- return this.bridge.cleanup();
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ if (this.bridge) {
38
+ yield this.bridge.cleanup();
39
+ this.bridge = null;
40
+ }
41
+ });
16
42
  }
17
43
  }
18
44
  exports.RLM = RLM;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recursive-llm-ts",
3
- "version": "1.0.7",
3
+ "version": "2.0.1",
4
4
  "description": "TypeScript bridge for recursive-llm: Recursive Language Models for unbounded context processing",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,9 +8,7 @@
8
8
  "dist",
9
9
  "recursive-llm/src",
10
10
  "recursive-llm/pyproject.toml",
11
- "scripts/install-python-deps.js",
12
- "scripts/apply-patches.js",
13
- "patches/core.py.patch"
11
+ "scripts/install-python-deps.js"
14
12
  ],
15
13
  "scripts": {
16
14
  "build": "tsc",
@@ -32,15 +30,23 @@
32
30
  "license": "MIT",
33
31
  "repository": {
34
32
  "type": "git",
35
- "url": "https://github.com/yourusername/recursive-llm-ts.git"
33
+ "url": "https://github.com/jbeck018/recursive-llm-ts.git"
36
34
  },
37
35
  "bugs": {
38
- "url": "https://github.com/yourusername/recursive-llm-ts/issues"
36
+ "url": "https://github.com/jbeck018/recursive-llm-ts/issues"
39
37
  },
40
- "homepage": "https://github.com/yourusername/recursive-llm-ts#readme",
38
+ "homepage": "https://github.com/jbeck018/recursive-llm-ts#readme",
41
39
  "dependencies": {
42
40
  "pythonia": "^1.2.6"
43
41
  },
42
+ "peerDependencies": {
43
+ "bunpy": "^0.1.0"
44
+ },
45
+ "peerDependenciesMeta": {
46
+ "bunpy": {
47
+ "optional": true
48
+ }
49
+ },
44
50
  "devDependencies": {
45
51
  "@types/node": "^20.11.19",
46
52
  "dotenv": "^16.4.5",
@@ -12,15 +12,8 @@ if (!fs.existsSync(pyprojectPath)) {
12
12
  process.exit(1);
13
13
  }
14
14
 
15
- // Apply patches first
16
- console.log('Applying patches to Python package...');
17
- try {
18
- execSync('node "' + path.join(__dirname, 'apply-patches.js') + '"', { stdio: 'inherit' });
19
- } catch (error) {
20
- console.error('Warning: Failed to apply patches. Continuing with installation...');
21
- }
22
-
23
15
  console.log('Installing Python dependencies for recursive-llm...');
16
+ console.log('Note: Python source is vendored with patches pre-applied.');
24
17
 
25
18
  try {
26
19
  // Install the Python package in editable mode
@@ -1,43 +0,0 @@
1
- diff --git a/src/rlm/core.py b/src/rlm/core.py
2
- index badb248..bcbb9c0 100644
3
- --- a/src/rlm/core.py
4
- +++ b/src/rlm/core.py
5
- @@ -54,14 +54,31 @@ class RLM:
6
- _current_depth: Internal current depth tracker
7
- **llm_kwargs: Additional LiteLLM parameters
8
- """
9
- - self.model = model
10
- - self.recursive_model = recursive_model or model
11
- - self.api_base = api_base
12
- - self.api_key = api_key
13
- - self.max_depth = max_depth
14
- - self.max_iterations = max_iterations
15
- + # Patch for recursive-llm-ts bug where config is passed as 2nd positional arg
16
- + if isinstance(recursive_model, dict):
17
- + config = recursive_model
18
- + # Reset recursive_model default
19
- + self.recursive_model = config.get('recursive_model', model)
20
- + self.api_base = config.get('api_base', api_base)
21
- + self.api_key = config.get('api_key', api_key)
22
- + self.max_depth = int(config.get('max_depth', max_depth))
23
- + self.max_iterations = int(config.get('max_iterations', max_iterations))
24
- +
25
- + # Extract other llm kwargs
26
- + excluded = {'recursive_model', 'api_base', 'api_key', 'max_depth', 'max_iterations'}
27
- + self.llm_kwargs = {k: v for k, v in config.items() if k not in excluded}
28
- + # Merge with any actual kwargs passed
29
- + self.llm_kwargs.update(llm_kwargs)
30
- + else:
31
- + self.recursive_model = recursive_model or model
32
- + self.api_base = api_base
33
- + self.api_key = api_key
34
- + self.max_depth = max_depth
35
- + self.max_iterations = max_iterations
36
- + self.llm_kwargs = llm_kwargs
37
- +
38
- self._current_depth = _current_depth
39
- - self.llm_kwargs = llm_kwargs
40
- + self.model = model
41
-
42
- self.repl = REPLExecutor()
43
-
@@ -1,88 +0,0 @@
1
- #!/usr/bin/env node
2
- const { execSync } = require('child_process');
3
- const path = require('path');
4
- const fs = require('fs');
5
-
6
- const corePyPath = path.join(__dirname, '..', 'recursive-llm', 'src', 'rlm', 'core.py');
7
- const patchPath = path.join(__dirname, '..', 'patches', 'core.py.patch');
8
-
9
- // Check if core.py exists
10
- if (!fs.existsSync(corePyPath)) {
11
- console.error('Error: core.py not found at', corePyPath);
12
- process.exit(1);
13
- }
14
-
15
- // Check if patch exists
16
- if (!fs.existsSync(patchPath)) {
17
- console.error('Error: patch file not found at', patchPath);
18
- process.exit(1);
19
- }
20
-
21
- console.log('Applying patches to recursive-llm Python package...');
22
-
23
- // Check if patch is already applied by looking for the patch marker
24
- const coreContent = fs.readFileSync(corePyPath, 'utf8');
25
- if (coreContent.includes('# Patch for recursive-llm-ts bug where config is passed as 2nd positional arg')) {
26
- console.log('✓ Patch already applied to core.py');
27
- process.exit(0);
28
- }
29
-
30
- // Apply the patch
31
- const pythonPackagePath = path.join(__dirname, '..', 'recursive-llm');
32
-
33
- try {
34
- // Try to apply patch
35
- execSync(`patch -p1 -i "${patchPath}"`, {
36
- cwd: pythonPackagePath,
37
- stdio: 'inherit'
38
- });
39
- console.log('✓ Successfully applied core.py patch');
40
- } catch (error) {
41
- console.error('Failed to apply patch using patch command.');
42
- console.error('Attempting manual patch application...');
43
-
44
- // Fallback: manually apply the patch by replacing the constructor
45
- try {
46
- const updatedContent = coreContent.replace(
47
- /(\s+)self\.model = model\n(\s+)self\.recursive_model = recursive_model or model\n(\s+)self\.api_base = api_base\n(\s+)self\.api_key = api_key\n(\s+)self\.max_depth = max_depth\n(\s+)self\.max_iterations = max_iterations\n(\s+)self\._current_depth = _current_depth\n(\s+)self\.llm_kwargs = llm_kwargs/,
48
- `$1# Patch for recursive-llm-ts bug where config is passed as 2nd positional arg
49
- $1if isinstance(recursive_model, dict):
50
- $1 config = recursive_model
51
- $1 # Reset recursive_model default
52
- $1 self.recursive_model = config.get('recursive_model', model)
53
- $1 self.api_base = config.get('api_base', api_base)
54
- $1 self.api_key = config.get('api_key', api_key)
55
- $1 self.max_depth = int(config.get('max_depth', max_depth))
56
- $1 self.max_iterations = int(config.get('max_iterations', max_iterations))
57
- $1
58
- $1 # Extract other llm kwargs
59
- $1 excluded = {'recursive_model', 'api_base', 'api_key', 'max_depth', 'max_iterations'}
60
- $1 self.llm_kwargs = {k: v for k, v in config.items() if k not in excluded}
61
- $1 # Merge with any actual kwargs passed
62
- $1 self.llm_kwargs.update(llm_kwargs)
63
- $1else:
64
- $1 self.recursive_model = recursive_model or model
65
- $1 self.api_base = api_base
66
- $1 self.api_key = api_key
67
- $1 self.max_depth = max_depth
68
- $1 self.max_iterations = max_iterations
69
- $1 self.llm_kwargs = llm_kwargs
70
-
71
- $1self._current_depth = _current_depth
72
- $1self.model = model`
73
- );
74
-
75
- if (updatedContent === coreContent) {
76
- console.error('Manual patch failed: pattern not found in core.py');
77
- console.error('The file may have been updated upstream.');
78
- console.error('Please manually apply the patch from patches/core.py.patch');
79
- process.exit(1);
80
- }
81
-
82
- fs.writeFileSync(corePyPath, updatedContent, 'utf8');
83
- console.log('✓ Successfully applied patch manually');
84
- } catch (manualError) {
85
- console.error('Manual patch application failed:', manualError.message);
86
- process.exit(1);
87
- }
88
- }