@cloudwarriors-ai/rlm 0.1.5

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 (220) hide show
  1. package/README.md +208 -0
  2. package/dist/application/index.d.ts +4 -0
  3. package/dist/application/index.d.ts.map +1 -0
  4. package/dist/application/index.js +4 -0
  5. package/dist/application/index.js.map +1 -0
  6. package/dist/application/query-handler.d.ts +49 -0
  7. package/dist/application/query-handler.d.ts.map +1 -0
  8. package/dist/application/query-handler.js +311 -0
  9. package/dist/application/query-handler.js.map +1 -0
  10. package/dist/application/rlm-service.d.ts +68 -0
  11. package/dist/application/rlm-service.d.ts.map +1 -0
  12. package/dist/application/rlm-service.js +132 -0
  13. package/dist/application/rlm-service.js.map +1 -0
  14. package/dist/application/session-manager.d.ts +70 -0
  15. package/dist/application/session-manager.d.ts.map +1 -0
  16. package/dist/application/session-manager.js +237 -0
  17. package/dist/application/session-manager.js.map +1 -0
  18. package/dist/cli/commands/config.d.ts +34 -0
  19. package/dist/cli/commands/config.d.ts.map +1 -0
  20. package/dist/cli/commands/config.js +157 -0
  21. package/dist/cli/commands/config.js.map +1 -0
  22. package/dist/cli/commands/index.d.ts +4 -0
  23. package/dist/cli/commands/index.d.ts.map +1 -0
  24. package/dist/cli/commands/index.js +4 -0
  25. package/dist/cli/commands/index.js.map +1 -0
  26. package/dist/cli/commands/query.d.ts +26 -0
  27. package/dist/cli/commands/query.d.ts.map +1 -0
  28. package/dist/cli/commands/query.js +90 -0
  29. package/dist/cli/commands/query.js.map +1 -0
  30. package/dist/cli/commands/session.d.ts +40 -0
  31. package/dist/cli/commands/session.d.ts.map +1 -0
  32. package/dist/cli/commands/session.js +55 -0
  33. package/dist/cli/commands/session.js.map +1 -0
  34. package/dist/cli/config-loader.d.ts +63 -0
  35. package/dist/cli/config-loader.d.ts.map +1 -0
  36. package/dist/cli/config-loader.js +94 -0
  37. package/dist/cli/config-loader.js.map +1 -0
  38. package/dist/cli/index.d.ts +3 -0
  39. package/dist/cli/index.d.ts.map +1 -0
  40. package/dist/cli/index.js +120 -0
  41. package/dist/cli/index.js.map +1 -0
  42. package/dist/cli/output/formatter.d.ts +24 -0
  43. package/dist/cli/output/formatter.d.ts.map +1 -0
  44. package/dist/cli/output/formatter.js +196 -0
  45. package/dist/cli/output/formatter.js.map +1 -0
  46. package/dist/cli/output/index.d.ts +3 -0
  47. package/dist/cli/output/index.d.ts.map +1 -0
  48. package/dist/cli/output/index.js +3 -0
  49. package/dist/cli/output/index.js.map +1 -0
  50. package/dist/cli/output/progress.d.ts +60 -0
  51. package/dist/cli/output/progress.d.ts.map +1 -0
  52. package/dist/cli/output/progress.js +142 -0
  53. package/dist/cli/output/progress.js.map +1 -0
  54. package/dist/domain/errors/base-error.d.ts +17 -0
  55. package/dist/domain/errors/base-error.d.ts.map +1 -0
  56. package/dist/domain/errors/base-error.js +29 -0
  57. package/dist/domain/errors/base-error.js.map +1 -0
  58. package/dist/domain/errors/execution-error.d.ts +61 -0
  59. package/dist/domain/errors/execution-error.d.ts.map +1 -0
  60. package/dist/domain/errors/execution-error.js +86 -0
  61. package/dist/domain/errors/execution-error.js.map +1 -0
  62. package/dist/domain/errors/index.d.ts +14 -0
  63. package/dist/domain/errors/index.d.ts.map +1 -0
  64. package/dist/domain/errors/index.js +26 -0
  65. package/dist/domain/errors/index.js.map +1 -0
  66. package/dist/domain/errors/limit-exceeded.d.ts +38 -0
  67. package/dist/domain/errors/limit-exceeded.d.ts.map +1 -0
  68. package/dist/domain/errors/limit-exceeded.js +71 -0
  69. package/dist/domain/errors/limit-exceeded.js.map +1 -0
  70. package/dist/domain/errors/llm-error.d.ts +60 -0
  71. package/dist/domain/errors/llm-error.d.ts.map +1 -0
  72. package/dist/domain/errors/llm-error.js +92 -0
  73. package/dist/domain/errors/llm-error.js.map +1 -0
  74. package/dist/domain/errors/validation-error.d.ts +58 -0
  75. package/dist/domain/errors/validation-error.d.ts.map +1 -0
  76. package/dist/domain/errors/validation-error.js +81 -0
  77. package/dist/domain/errors/validation-error.js.map +1 -0
  78. package/dist/domain/interfaces/code-executor.d.ts +98 -0
  79. package/dist/domain/interfaces/code-executor.d.ts.map +1 -0
  80. package/dist/domain/interfaces/code-executor.js +2 -0
  81. package/dist/domain/interfaces/code-executor.js.map +1 -0
  82. package/dist/domain/interfaces/event-emitter.d.ts +137 -0
  83. package/dist/domain/interfaces/event-emitter.d.ts.map +1 -0
  84. package/dist/domain/interfaces/event-emitter.js +2 -0
  85. package/dist/domain/interfaces/event-emitter.js.map +1 -0
  86. package/dist/domain/interfaces/index.d.ts +5 -0
  87. package/dist/domain/interfaces/index.d.ts.map +1 -0
  88. package/dist/domain/interfaces/index.js +2 -0
  89. package/dist/domain/interfaces/index.js.map +1 -0
  90. package/dist/domain/interfaces/llm-provider.d.ts +64 -0
  91. package/dist/domain/interfaces/llm-provider.d.ts.map +1 -0
  92. package/dist/domain/interfaces/llm-provider.js +2 -0
  93. package/dist/domain/interfaces/llm-provider.js.map +1 -0
  94. package/dist/domain/interfaces/session-store.d.ts +65 -0
  95. package/dist/domain/interfaces/session-store.d.ts.map +1 -0
  96. package/dist/domain/interfaces/session-store.js +2 -0
  97. package/dist/domain/interfaces/session-store.js.map +1 -0
  98. package/dist/domain/services/context-chunker.d.ts +43 -0
  99. package/dist/domain/services/context-chunker.d.ts.map +1 -0
  100. package/dist/domain/services/context-chunker.js +152 -0
  101. package/dist/domain/services/context-chunker.js.map +1 -0
  102. package/dist/domain/services/cost-calculator.d.ts +63 -0
  103. package/dist/domain/services/cost-calculator.d.ts.map +1 -0
  104. package/dist/domain/services/cost-calculator.js +121 -0
  105. package/dist/domain/services/cost-calculator.js.map +1 -0
  106. package/dist/domain/services/index.d.ts +5 -0
  107. package/dist/domain/services/index.d.ts.map +1 -0
  108. package/dist/domain/services/index.js +9 -0
  109. package/dist/domain/services/index.js.map +1 -0
  110. package/dist/domain/services/limit-checker.d.ts +54 -0
  111. package/dist/domain/services/limit-checker.d.ts.map +1 -0
  112. package/dist/domain/services/limit-checker.js +146 -0
  113. package/dist/domain/services/limit-checker.js.map +1 -0
  114. package/dist/domain/services/result-aggregator.d.ts +49 -0
  115. package/dist/domain/services/result-aggregator.d.ts.map +1 -0
  116. package/dist/domain/services/result-aggregator.js +131 -0
  117. package/dist/domain/services/result-aggregator.js.map +1 -0
  118. package/dist/domain/types/config.d.ts +41 -0
  119. package/dist/domain/types/config.d.ts.map +1 -0
  120. package/dist/domain/types/config.js +22 -0
  121. package/dist/domain/types/config.js.map +1 -0
  122. package/dist/domain/types/context.d.ts +64 -0
  123. package/dist/domain/types/context.d.ts.map +1 -0
  124. package/dist/domain/types/context.js +20 -0
  125. package/dist/domain/types/context.js.map +1 -0
  126. package/dist/domain/types/index.d.ts +5 -0
  127. package/dist/domain/types/index.d.ts.map +1 -0
  128. package/dist/domain/types/index.js +9 -0
  129. package/dist/domain/types/index.js.map +1 -0
  130. package/dist/domain/types/result.d.ts +137 -0
  131. package/dist/domain/types/result.d.ts.map +1 -0
  132. package/dist/domain/types/result.js +27 -0
  133. package/dist/domain/types/result.js.map +1 -0
  134. package/dist/domain/types/session.d.ts +74 -0
  135. package/dist/domain/types/session.d.ts.map +1 -0
  136. package/dist/domain/types/session.js +31 -0
  137. package/dist/domain/types/session.js.map +1 -0
  138. package/dist/factory/create-rlm.d.ts +77 -0
  139. package/dist/factory/create-rlm.d.ts.map +1 -0
  140. package/dist/factory/create-rlm.js +82 -0
  141. package/dist/factory/create-rlm.js.map +1 -0
  142. package/dist/factory/default-config.d.ts +27 -0
  143. package/dist/factory/default-config.d.ts.map +1 -0
  144. package/dist/factory/default-config.js +98 -0
  145. package/dist/factory/default-config.js.map +1 -0
  146. package/dist/factory/index.d.ts +3 -0
  147. package/dist/factory/index.d.ts.map +1 -0
  148. package/dist/factory/index.js +3 -0
  149. package/dist/factory/index.js.map +1 -0
  150. package/dist/index.d.ts +37 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +40 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/infrastructure/events/event-types.d.ts +35 -0
  155. package/dist/infrastructure/events/event-types.d.ts.map +1 -0
  156. package/dist/infrastructure/events/event-types.js +44 -0
  157. package/dist/infrastructure/events/event-types.js.map +1 -0
  158. package/dist/infrastructure/events/index.d.ts +3 -0
  159. package/dist/infrastructure/events/index.d.ts.map +1 -0
  160. package/dist/infrastructure/events/index.js +3 -0
  161. package/dist/infrastructure/events/index.js.map +1 -0
  162. package/dist/infrastructure/events/node-emitter.d.ts +72 -0
  163. package/dist/infrastructure/events/node-emitter.d.ts.map +1 -0
  164. package/dist/infrastructure/events/node-emitter.js +125 -0
  165. package/dist/infrastructure/events/node-emitter.js.map +1 -0
  166. package/dist/infrastructure/llm/index.d.ts +3 -0
  167. package/dist/infrastructure/llm/index.d.ts.map +1 -0
  168. package/dist/infrastructure/llm/index.js +3 -0
  169. package/dist/infrastructure/llm/index.js.map +1 -0
  170. package/dist/infrastructure/llm/openrouter-provider.d.ts +35 -0
  171. package/dist/infrastructure/llm/openrouter-provider.d.ts.map +1 -0
  172. package/dist/infrastructure/llm/openrouter-provider.js +158 -0
  173. package/dist/infrastructure/llm/openrouter-provider.js.map +1 -0
  174. package/dist/infrastructure/llm/prompts/code-gen-prompt.d.ts +21 -0
  175. package/dist/infrastructure/llm/prompts/code-gen-prompt.d.ts.map +1 -0
  176. package/dist/infrastructure/llm/prompts/code-gen-prompt.js +78 -0
  177. package/dist/infrastructure/llm/prompts/code-gen-prompt.js.map +1 -0
  178. package/dist/infrastructure/llm/prompts/error-recovery-prompt.d.ts +24 -0
  179. package/dist/infrastructure/llm/prompts/error-recovery-prompt.d.ts.map +1 -0
  180. package/dist/infrastructure/llm/prompts/error-recovery-prompt.js +70 -0
  181. package/dist/infrastructure/llm/prompts/error-recovery-prompt.js.map +1 -0
  182. package/dist/infrastructure/llm/prompts/index.d.ts +4 -0
  183. package/dist/infrastructure/llm/prompts/index.d.ts.map +1 -0
  184. package/dist/infrastructure/llm/prompts/index.js +4 -0
  185. package/dist/infrastructure/llm/prompts/index.js.map +1 -0
  186. package/dist/infrastructure/llm/prompts/system-prompt.d.ts +12 -0
  187. package/dist/infrastructure/llm/prompts/system-prompt.d.ts.map +1 -0
  188. package/dist/infrastructure/llm/prompts/system-prompt.js +96 -0
  189. package/dist/infrastructure/llm/prompts/system-prompt.js.map +1 -0
  190. package/dist/infrastructure/persistence/index.d.ts +3 -0
  191. package/dist/infrastructure/persistence/index.d.ts.map +1 -0
  192. package/dist/infrastructure/persistence/index.js +3 -0
  193. package/dist/infrastructure/persistence/index.js.map +1 -0
  194. package/dist/infrastructure/persistence/memory-store.d.ts +24 -0
  195. package/dist/infrastructure/persistence/memory-store.d.ts.map +1 -0
  196. package/dist/infrastructure/persistence/memory-store.js +71 -0
  197. package/dist/infrastructure/persistence/memory-store.js.map +1 -0
  198. package/dist/infrastructure/persistence/schema.d.ts +120 -0
  199. package/dist/infrastructure/persistence/schema.d.ts.map +1 -0
  200. package/dist/infrastructure/persistence/schema.js +130 -0
  201. package/dist/infrastructure/persistence/schema.js.map +1 -0
  202. package/dist/infrastructure/sandbox/ast-validator.d.ts +23 -0
  203. package/dist/infrastructure/sandbox/ast-validator.d.ts.map +1 -0
  204. package/dist/infrastructure/sandbox/ast-validator.js +249 -0
  205. package/dist/infrastructure/sandbox/ast-validator.js.map +1 -0
  206. package/dist/infrastructure/sandbox/index.d.ts +4 -0
  207. package/dist/infrastructure/sandbox/index.d.ts.map +1 -0
  208. package/dist/infrastructure/sandbox/index.js +4 -0
  209. package/dist/infrastructure/sandbox/index.js.map +1 -0
  210. package/dist/infrastructure/sandbox/prelude/rlm_prelude.py +376 -0
  211. package/dist/infrastructure/sandbox/process-manager.d.ts +98 -0
  212. package/dist/infrastructure/sandbox/process-manager.d.ts.map +1 -0
  213. package/dist/infrastructure/sandbox/process-manager.js +186 -0
  214. package/dist/infrastructure/sandbox/process-manager.js.map +1 -0
  215. package/dist/infrastructure/sandbox/python-executor.d.ts +29 -0
  216. package/dist/infrastructure/sandbox/python-executor.d.ts.map +1 -0
  217. package/dist/infrastructure/sandbox/python-executor.js +182 -0
  218. package/dist/infrastructure/sandbox/python-executor.js.map +1 -0
  219. package/package.json +65 -0
  220. package/src/infrastructure/sandbox/prelude/rlm_prelude.py +376 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-executor.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/sandbox/python-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAKjB,MAAM,0CAA0C,CAAC;AASlD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAE9B,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED;;GAEG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IAExD,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,kBAAkB,CAAyC;gBAEvD,MAAM,GAAE,oBAAyB;IAS7C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAIlC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAiI1E,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,OAAO,IAAI,OAAO;IAIlB,OAAO,CAAC,cAAc;CAgCvB"}
@@ -0,0 +1,182 @@
1
+ import { ExecutionError, ExecutionTimeoutError, CodeValidationError, } from '../../domain/errors/index.js';
2
+ import { ASTValidator } from './ast-validator.js';
3
+ import { ProcessManager } from './process-manager.js';
4
+ /**
5
+ * Python code executor implementation
6
+ */
7
+ export class PythonExecutor {
8
+ validator;
9
+ processManager;
10
+ config;
11
+ currentProcess = null;
12
+ pendingQueryResolve = null;
13
+ pendingQueryReject = null;
14
+ constructor(config = {}) {
15
+ this.config = {
16
+ strictMode: config.strictMode ?? true,
17
+ defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,
18
+ };
19
+ this.validator = new ASTValidator(this.config.strictMode);
20
+ this.processManager = new ProcessManager();
21
+ }
22
+ validate(code) {
23
+ return this.validator.validate(code);
24
+ }
25
+ async execute(code, context) {
26
+ // Validate code first
27
+ const validation = this.validate(code);
28
+ if (!validation.valid) {
29
+ throw new CodeValidationError('Code validation failed', validation.errors.map((e) => ({
30
+ line: e.line,
31
+ column: e.column,
32
+ message: e.message,
33
+ code: e.code,
34
+ })), context.sessionId);
35
+ }
36
+ const startTime = Date.now();
37
+ const commands = [];
38
+ let stdout = '';
39
+ let stderr = '';
40
+ let result;
41
+ let error;
42
+ return new Promise((resolve, reject) => {
43
+ const timeoutMs = context.timeoutMs || this.config.defaultTimeoutMs;
44
+ // Spawn Python process
45
+ const process = this.processManager.spawn({ timeoutMs });
46
+ this.currentProcess = process;
47
+ // Handle stdout
48
+ process.on('stdout', (data) => {
49
+ stdout += data;
50
+ });
51
+ // Handle stderr
52
+ process.on('stderr', (data) => {
53
+ stderr += data;
54
+ });
55
+ // Handle commands from Python
56
+ process.on('command', (command) => {
57
+ commands.push(this.convertCommand(command));
58
+ if (command.type === 'set_result') {
59
+ const payload = command.payload;
60
+ result = payload.result;
61
+ }
62
+ });
63
+ // Handle process exit
64
+ process.on('exit', (code, signal) => {
65
+ this.currentProcess = null;
66
+ const executionTimeMs = Date.now() - startTime;
67
+ // Check for errors in output
68
+ const errorMatch = stdout.match(/__ERROR__:(.+)/);
69
+ if (errorMatch) {
70
+ try {
71
+ const errorData = JSON.parse(errorMatch[1]);
72
+ error = errorData.error;
73
+ resolve({
74
+ success: false,
75
+ stdout: stdout.replace(/__ERROR__:.+\n?/, ''),
76
+ stderr,
77
+ error: errorData.error,
78
+ executionTimeMs,
79
+ commands,
80
+ });
81
+ return;
82
+ }
83
+ catch {
84
+ error = errorMatch[1];
85
+ }
86
+ }
87
+ // Check if we got a result
88
+ const success = result !== undefined || stdout.includes('__DONE__');
89
+ resolve({
90
+ success,
91
+ stdout: stdout
92
+ .replace(/__DONE__\n?/, '')
93
+ .replace(/__WARNING__:.+\n?/g, '')
94
+ .replace(/__COMMAND__:.+\n?/g, ''),
95
+ stderr,
96
+ result,
97
+ error,
98
+ executionTimeMs,
99
+ commands,
100
+ });
101
+ });
102
+ // Handle process error
103
+ process.on('error', (err) => {
104
+ this.currentProcess = null;
105
+ const executionTimeMs = Date.now() - startTime;
106
+ if (err.message.includes('timed out')) {
107
+ reject(new ExecutionTimeoutError(timeoutMs, context.sessionId));
108
+ }
109
+ else {
110
+ reject(new ExecutionError(err.message, {
111
+ sessionId: context.sessionId,
112
+ sourceCode: code,
113
+ }));
114
+ }
115
+ });
116
+ // Send initialization command with context and code
117
+ const contextObj = {};
118
+ for (const [name, value] of context.variables) {
119
+ contextObj[name] = value;
120
+ }
121
+ const initCommand = {
122
+ context: contextObj,
123
+ code,
124
+ };
125
+ process.write(`__INIT__:${JSON.stringify(initCommand)}\n`);
126
+ });
127
+ }
128
+ async respondToQuery(response) {
129
+ if (this.currentProcess && this.currentProcess.isRunning()) {
130
+ this.currentProcess.respond({ result: response });
131
+ }
132
+ if (this.pendingQueryResolve) {
133
+ this.pendingQueryResolve(response);
134
+ this.pendingQueryResolve = null;
135
+ this.pendingQueryReject = null;
136
+ }
137
+ }
138
+ async kill() {
139
+ if (this.currentProcess) {
140
+ this.currentProcess.kill();
141
+ this.currentProcess = null;
142
+ }
143
+ if (this.pendingQueryReject) {
144
+ this.pendingQueryReject(new Error('Execution cancelled'));
145
+ this.pendingQueryResolve = null;
146
+ this.pendingQueryReject = null;
147
+ }
148
+ }
149
+ isReady() {
150
+ return this.currentProcess === null || !this.currentProcess.isRunning();
151
+ }
152
+ convertCommand(command) {
153
+ switch (command.type) {
154
+ case 'llm_query': {
155
+ const payload = command.payload;
156
+ return {
157
+ type: 'llm_query',
158
+ query: payload.query,
159
+ contextVariables: payload.context,
160
+ };
161
+ }
162
+ case 'set_result': {
163
+ const payload = command.payload;
164
+ return {
165
+ type: 'set_result',
166
+ result: payload.result,
167
+ };
168
+ }
169
+ case 'set_variable': {
170
+ const payload = command.payload;
171
+ return {
172
+ type: 'set_variable',
173
+ name: payload.name,
174
+ value: payload.value,
175
+ };
176
+ }
177
+ default:
178
+ throw new Error(`Unknown command type: ${command.type}`);
179
+ }
180
+ }
181
+ }
182
+ //# sourceMappingURL=python-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-executor.js","sourceRoot":"","sources":["../../../src/infrastructure/sandbox/python-executor.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@cloudwarriors-ai/rlm",
3
+ "version": "0.1.5",
4
+ "description": "Recursive Language Model - Process massive contexts through recursive LLM decomposition",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "rlm": "./dist/cli/index.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./types": {
17
+ "types": "./dist/domain/types/index.d.ts",
18
+ "import": "./dist/domain/types/index.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src/infrastructure/sandbox/prelude"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc && cp -r src/infrastructure/sandbox/prelude dist/infrastructure/sandbox/",
27
+ "dev": "tsc --watch",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "test:coverage": "vitest run --coverage",
31
+ "lint": "tsc --noEmit",
32
+ "prepublishOnly": "npm run build",
33
+ "clean": "rm -rf dist"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/cloudwarriors-ai/rlm.git"
38
+ },
39
+ "keywords": [
40
+ "llm",
41
+ "recursive",
42
+ "context",
43
+ "openrouter",
44
+ "claude",
45
+ "ai"
46
+ ],
47
+ "author": "CloudWarriors AI",
48
+ "license": "UNLICENSED",
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "engines": {
53
+ "node": ">=20.0.0"
54
+ },
55
+ "dependencies": {
56
+ "commander": "^12.1.0",
57
+ "nanoid": "^5.0.7",
58
+ "zod": "^3.23.8"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^20.14.0",
62
+ "typescript": "^5.4.5",
63
+ "vitest": "^1.6.0"
64
+ }
65
+ }
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ RLM Python Prelude
4
+
5
+ This module provides the runtime environment for RLM code execution.
6
+ It defines the special functions available to user code and handles
7
+ communication with the Node.js parent process.
8
+ """
9
+
10
+ import sys
11
+ import json
12
+ import builtins
13
+ from typing import Any, Optional
14
+
15
+ # Store for context variables
16
+ _context_store: dict[str, str] = {}
17
+
18
+ # Result storage
19
+ _result: Optional[str] = None
20
+
21
+ # Command counter for tracking
22
+ _command_id: int = 0
23
+
24
+
25
+ def _send_command(command_type: str, payload: Any) -> None:
26
+ """Send a command to the Node.js parent process."""
27
+ global _command_id
28
+ _command_id += 1
29
+ command = {
30
+ "id": _command_id,
31
+ "type": command_type,
32
+ "payload": payload
33
+ }
34
+ print(f"__COMMAND__:{json.dumps(command)}", flush=True)
35
+
36
+
37
+ def _wait_for_response() -> Any:
38
+ """Wait for a response from the Node.js parent process."""
39
+ while True:
40
+ line = sys.stdin.readline()
41
+ if not line:
42
+ raise RuntimeError("Parent process closed stdin")
43
+
44
+ line = line.strip()
45
+ if line.startswith("__RESPONSE__:"):
46
+ try:
47
+ return json.loads(line[len("__RESPONSE__:"):])
48
+ except json.JSONDecodeError as e:
49
+ raise RuntimeError(f"Invalid response JSON: {e}")
50
+
51
+
52
+ def llm_query(query: str, *context_vars: str) -> str:
53
+ """
54
+ Make a recursive LLM query.
55
+
56
+ Args:
57
+ query: The question or task for the LLM
58
+ *context_vars: Variable names or string values to include as context
59
+
60
+ Returns:
61
+ The LLM's response as a string
62
+
63
+ Example:
64
+ result = llm_query("Summarize this text", "context")
65
+ result = llm_query("What are the main points?", chunk1, chunk2)
66
+ """
67
+ # Resolve context variables
68
+ context_values = []
69
+ for var in context_vars:
70
+ if var in _context_store:
71
+ context_values.append(_context_store[var])
72
+ elif isinstance(var, str):
73
+ # Treat as literal string value
74
+ context_values.append(var)
75
+ else:
76
+ raise ValueError(f"Context variable not found: {var}")
77
+
78
+ # Send the query command
79
+ _send_command("llm_query", {
80
+ "query": query,
81
+ "context": context_values
82
+ })
83
+
84
+ # Wait for response
85
+ response = _wait_for_response()
86
+
87
+ if "error" in response:
88
+ raise RuntimeError(f"LLM query failed: {response['error']}")
89
+
90
+ return response.get("result", "")
91
+
92
+
93
+ def set_result(result: str) -> None:
94
+ """
95
+ Set the final result of the RLM execution.
96
+
97
+ Args:
98
+ result: The final answer/result to return
99
+
100
+ Example:
101
+ set_result("The analysis shows three main points...")
102
+ """
103
+ global _result
104
+ _result = str(result)
105
+ _send_command("set_result", {"result": _result})
106
+
107
+
108
+ def set_variable(name: str, value: str) -> None:
109
+ """
110
+ Store a variable for use in subsequent code or queries.
111
+
112
+ Args:
113
+ name: Variable name (valid Python identifier)
114
+ value: Value to store (will be converted to string)
115
+
116
+ Example:
117
+ set_variable("summary", "Key findings from chunk 1...")
118
+ """
119
+ if not name.isidentifier():
120
+ raise ValueError(f"Invalid variable name: {name}")
121
+
122
+ _context_store[name] = str(value)
123
+ _send_command("set_variable", {"name": name, "value": str(value)})
124
+
125
+
126
+ def chunk_text(text: str, chunk_size: int = 10000, overlap: int = 500) -> list[str]:
127
+ """
128
+ Split text into overlapping chunks.
129
+
130
+ Args:
131
+ text: The text to split
132
+ chunk_size: Maximum characters per chunk
133
+ overlap: Number of characters to overlap between chunks
134
+
135
+ Returns:
136
+ List of text chunks
137
+
138
+ Example:
139
+ chunks = chunk_text(context, chunk_size=5000)
140
+ for i, chunk in enumerate(chunks):
141
+ result = llm_query(f"Analyze chunk {i+1}", chunk)
142
+ """
143
+ if chunk_size <= overlap:
144
+ raise ValueError("chunk_size must be greater than overlap")
145
+
146
+ chunks = []
147
+ start = 0
148
+
149
+ while start < len(text):
150
+ end = start + chunk_size
151
+ chunk = text[start:end]
152
+
153
+ # Try to break at a newline or space
154
+ if end < len(text):
155
+ # Look for a good break point in the last 10% of the chunk
156
+ break_zone = chunk[int(chunk_size * 0.9):]
157
+
158
+ # Prefer paragraph break
159
+ para_break = break_zone.rfind('\n\n')
160
+ if para_break != -1:
161
+ end = start + int(chunk_size * 0.9) + para_break + 2
162
+ chunk = text[start:end]
163
+ else:
164
+ # Fall back to line break
165
+ line_break = break_zone.rfind('\n')
166
+ if line_break != -1:
167
+ end = start + int(chunk_size * 0.9) + line_break + 1
168
+ chunk = text[start:end]
169
+ else:
170
+ # Fall back to space
171
+ space_break = break_zone.rfind(' ')
172
+ if space_break != -1:
173
+ end = start + int(chunk_size * 0.9) + space_break + 1
174
+ chunk = text[start:end]
175
+
176
+ chunks.append(chunk.strip())
177
+ start = end - overlap
178
+
179
+ return [c for c in chunks if c] # Filter empty chunks
180
+
181
+
182
+ def filter_lines(text: str, predicate: str) -> str:
183
+ """
184
+ Filter lines in text based on a predicate.
185
+
186
+ Args:
187
+ text: The text to filter
188
+ predicate: A string that matching lines must contain
189
+
190
+ Returns:
191
+ Filtered text with only matching lines
192
+
193
+ Example:
194
+ errors = filter_lines(log_content, "ERROR")
195
+ """
196
+ lines = text.split('\n')
197
+ filtered = [line for line in lines if predicate in line]
198
+ return '\n'.join(filtered)
199
+
200
+
201
+ def count_tokens(text: str) -> int:
202
+ """
203
+ Estimate the token count for text.
204
+
205
+ This is a rough estimate based on ~4 characters per token.
206
+
207
+ Args:
208
+ text: The text to estimate
209
+
210
+ Returns:
211
+ Estimated token count
212
+ """
213
+ return len(text) // 4
214
+
215
+
216
+ # Safe modules that can be imported (defined first so _restricted_import can use it)
217
+ _SAFE_MODULES = {
218
+ 'json': __import__('json'),
219
+ 're': __import__('re'),
220
+ 'collections': __import__('collections'),
221
+ 'itertools': __import__('itertools'),
222
+ 'functools': __import__('functools'),
223
+ 'math': __import__('math'),
224
+ 'random': __import__('random'),
225
+ 'string': __import__('string'),
226
+ 'textwrap': __import__('textwrap'),
227
+ 'difflib': __import__('difflib'),
228
+ 'heapq': __import__('heapq'),
229
+ 'bisect': __import__('bisect'),
230
+ 'copy': __import__('copy'),
231
+ }
232
+
233
+
234
+ def _restricted_import(name: str, globals_dict=None, locals_dict=None, fromlist=(), level=0):
235
+ """Restricted import function that only allows safe modules."""
236
+ if name in _SAFE_MODULES:
237
+ return _SAFE_MODULES[name]
238
+ raise ImportError(f"Import of '{name}' is not allowed in RLM sandbox")
239
+
240
+
241
+ # Restricted builtins for sandboxed execution
242
+ _SAFE_BUILTINS = {
243
+ # Restricted import (must be in builtins for 'import' statement to work)
244
+ '__import__': _restricted_import,
245
+
246
+ # Safe types
247
+ 'bool': bool,
248
+ 'int': int,
249
+ 'float': float,
250
+ 'str': str,
251
+ 'list': list,
252
+ 'dict': dict,
253
+ 'tuple': tuple,
254
+ 'set': set,
255
+ 'frozenset': frozenset,
256
+ 'bytes': bytes,
257
+ 'bytearray': bytearray,
258
+
259
+ # Safe functions
260
+ 'abs': abs,
261
+ 'all': all,
262
+ 'any': any,
263
+ 'bin': bin,
264
+ 'chr': chr,
265
+ 'divmod': divmod,
266
+ 'enumerate': enumerate,
267
+ 'filter': filter,
268
+ 'format': format,
269
+ 'hex': hex,
270
+ 'isinstance': isinstance,
271
+ 'issubclass': issubclass,
272
+ 'iter': iter,
273
+ 'len': len,
274
+ 'map': map,
275
+ 'max': max,
276
+ 'min': min,
277
+ 'next': next,
278
+ 'oct': oct,
279
+ 'ord': ord,
280
+ 'pow': pow,
281
+ 'print': print,
282
+ 'range': range,
283
+ 'repr': repr,
284
+ 'reversed': reversed,
285
+ 'round': round,
286
+ 'slice': slice,
287
+ 'sorted': sorted,
288
+ 'sum': sum,
289
+ 'type': type,
290
+ 'zip': zip,
291
+
292
+ # Exceptions
293
+ 'Exception': Exception,
294
+ 'ValueError': ValueError,
295
+ 'TypeError': TypeError,
296
+ 'KeyError': KeyError,
297
+ 'IndexError': IndexError,
298
+ 'RuntimeError': RuntimeError,
299
+ 'StopIteration': StopIteration,
300
+
301
+ # Constants
302
+ 'True': True,
303
+ 'False': False,
304
+ 'None': None,
305
+
306
+ # RLM functions
307
+ 'llm_query': llm_query,
308
+ 'set_result': set_result,
309
+ 'set_variable': set_variable,
310
+ 'chunk_text': chunk_text,
311
+ 'filter_lines': filter_lines,
312
+ 'count_tokens': count_tokens,
313
+ }
314
+
315
+
316
+ def main():
317
+ """Main entry point for RLM prelude."""
318
+ # Read initial context
319
+ try:
320
+ init_line = sys.stdin.readline().strip()
321
+ if init_line.startswith("__INIT__:"):
322
+ init_data = json.loads(init_line[len("__INIT__:"):])
323
+
324
+ # Load context variables
325
+ for name, value in init_data.get("context", {}).items():
326
+ _context_store[name] = value
327
+
328
+ # Get the code to execute
329
+ code = init_data.get("code", "")
330
+
331
+ if not code:
332
+ print("__ERROR__:No code provided", flush=True)
333
+ return 1
334
+
335
+ # Create restricted execution environment
336
+ exec_globals = {
337
+ '__builtins__': _SAFE_BUILTINS,
338
+ '__name__': '__main__',
339
+ '__doc__': None,
340
+ }
341
+
342
+ # Add context variables to globals
343
+ exec_globals.update(_context_store)
344
+
345
+ # Execute the code
346
+ try:
347
+ exec(code, exec_globals)
348
+
349
+ # Check if result was set
350
+ if _result is None:
351
+ print("__WARNING__:No result was set. Call set_result() with your answer.", flush=True)
352
+
353
+ print("__DONE__", flush=True)
354
+ return 0
355
+
356
+ except Exception as e:
357
+ import traceback
358
+ tb = traceback.format_exc()
359
+ error_info = {
360
+ "error": str(e),
361
+ "type": type(e).__name__,
362
+ "traceback": tb
363
+ }
364
+ print(f"__ERROR__:{json.dumps(error_info)}", flush=True)
365
+ return 1
366
+ else:
367
+ print("__ERROR__:Invalid initialization", flush=True)
368
+ return 1
369
+
370
+ except Exception as e:
371
+ print(f"__ERROR__:{json.dumps({'error': str(e), 'type': type(e).__name__})}", flush=True)
372
+ return 1
373
+
374
+
375
+ if __name__ == "__main__":
376
+ sys.exit(main())