@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,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())
@@ -0,0 +1,98 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import { EventEmitter } from 'node:events';
3
+ /**
4
+ * Options for spawning a Python process
5
+ */
6
+ export interface SpawnOptions {
7
+ /** Timeout in milliseconds */
8
+ readonly timeoutMs: number;
9
+ /** Working directory */
10
+ readonly cwd?: string;
11
+ /** Environment variables */
12
+ readonly env?: Record<string, string>;
13
+ }
14
+ /**
15
+ * Events emitted by PythonProcess
16
+ */
17
+ export interface PythonProcessEvents {
18
+ stdout: (data: string) => void;
19
+ stderr: (data: string) => void;
20
+ command: (command: PythonProcessCommand) => void;
21
+ exit: (code: number | null, signal: string | null) => void;
22
+ error: (error: Error) => void;
23
+ }
24
+ /**
25
+ * Command from Python process
26
+ */
27
+ export interface PythonProcessCommand {
28
+ type: 'llm_query' | 'set_result' | 'set_variable';
29
+ payload: unknown;
30
+ }
31
+ /**
32
+ * A managed Python process
33
+ */
34
+ export declare class PythonProcess extends EventEmitter {
35
+ private readonly process;
36
+ private readonly timeout;
37
+ private killed;
38
+ private stdoutBuffer;
39
+ private stderrBuffer;
40
+ constructor(process: ChildProcess, timeoutMs: number);
41
+ /**
42
+ * Send input to the process
43
+ */
44
+ write(data: string): void;
45
+ /**
46
+ * Send a command response to the process
47
+ */
48
+ respond(response: unknown): void;
49
+ /**
50
+ * Kill the process
51
+ */
52
+ kill(signal?: NodeJS.Signals): void;
53
+ /**
54
+ * Check if the process is still running
55
+ */
56
+ isRunning(): boolean;
57
+ /**
58
+ * Get the process PID
59
+ */
60
+ get pid(): number | undefined;
61
+ /**
62
+ * Get collected stdout
63
+ */
64
+ getStdout(): string;
65
+ /**
66
+ * Get collected stderr
67
+ */
68
+ getStderr(): string;
69
+ /**
70
+ * Process stdout to extract commands
71
+ */
72
+ private processOutput;
73
+ }
74
+ /**
75
+ * Manages Python process lifecycle
76
+ */
77
+ export declare class ProcessManager {
78
+ private activeProcesses;
79
+ private readonly preludePath;
80
+ constructor();
81
+ /**
82
+ * Spawn a new Python process
83
+ */
84
+ spawn(options: SpawnOptions): PythonProcess;
85
+ /**
86
+ * Kill a specific process
87
+ */
88
+ kill(process: PythonProcess): void;
89
+ /**
90
+ * Kill all active processes
91
+ */
92
+ killAll(): void;
93
+ /**
94
+ * Get count of active processes
95
+ */
96
+ get activeCount(): number;
97
+ }
98
+ //# sourceMappingURL=process-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/sandbox/process-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,wBAAwB;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,4BAA4B;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACjD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,WAAW,GAAG,YAAY,GAAG,cAAc,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,YAAY,CAAM;gBAEd,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM;IAqCpD;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAKhC;;OAEG;IACH,IAAI,CAAC,MAAM,GAAE,MAAM,CAAC,OAAmB,GAAG,IAAI;IAQ9C;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,GAAG,SAAS,CAE5B;IAED;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,OAAO,CAAC,aAAa;CAmCtB;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;;IAQrC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,aAAa;IAwB3C;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAKlC;;OAEG;IACH,OAAO,IAAI,IAAI;IAOf;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;CACF"}
@@ -0,0 +1,186 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { EventEmitter } from 'node:events';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ /**
6
+ * A managed Python process
7
+ */
8
+ export class PythonProcess extends EventEmitter {
9
+ process;
10
+ timeout;
11
+ killed = false;
12
+ stdoutBuffer = '';
13
+ stderrBuffer = '';
14
+ constructor(process, timeoutMs) {
15
+ super();
16
+ this.process = process;
17
+ // Set up timeout
18
+ this.timeout = setTimeout(() => {
19
+ this.kill('SIGKILL');
20
+ this.emit('error', new Error(`Process timed out after ${timeoutMs}ms`));
21
+ }, timeoutMs);
22
+ // Handle stdout
23
+ process.stdout?.on('data', (data) => {
24
+ const text = data.toString();
25
+ this.stdoutBuffer += text;
26
+ this.processOutput();
27
+ });
28
+ // Handle stderr
29
+ process.stderr?.on('data', (data) => {
30
+ const text = data.toString();
31
+ this.stderrBuffer += text;
32
+ this.emit('stderr', text);
33
+ });
34
+ // Handle exit
35
+ process.on('exit', (code, signal) => {
36
+ clearTimeout(this.timeout);
37
+ this.emit('exit', code, signal);
38
+ });
39
+ // Handle errors
40
+ process.on('error', (error) => {
41
+ clearTimeout(this.timeout);
42
+ this.emit('error', error);
43
+ });
44
+ }
45
+ /**
46
+ * Send input to the process
47
+ */
48
+ write(data) {
49
+ this.process.stdin?.write(data);
50
+ }
51
+ /**
52
+ * Send a command response to the process
53
+ */
54
+ respond(response) {
55
+ const json = JSON.stringify(response);
56
+ this.write(`__RESPONSE__:${json}\n`);
57
+ }
58
+ /**
59
+ * Kill the process
60
+ */
61
+ kill(signal = 'SIGTERM') {
62
+ if (!this.killed) {
63
+ this.killed = true;
64
+ clearTimeout(this.timeout);
65
+ this.process.kill(signal);
66
+ }
67
+ }
68
+ /**
69
+ * Check if the process is still running
70
+ */
71
+ isRunning() {
72
+ return !this.killed && this.process.exitCode === null;
73
+ }
74
+ /**
75
+ * Get the process PID
76
+ */
77
+ get pid() {
78
+ return this.process.pid;
79
+ }
80
+ /**
81
+ * Get collected stdout
82
+ */
83
+ getStdout() {
84
+ return this.stdoutBuffer;
85
+ }
86
+ /**
87
+ * Get collected stderr
88
+ */
89
+ getStderr() {
90
+ return this.stderrBuffer;
91
+ }
92
+ /**
93
+ * Process stdout to extract commands
94
+ */
95
+ processOutput() {
96
+ // Look for command markers in output
97
+ const lines = this.stdoutBuffer.split('\n');
98
+ const remainingLines = [];
99
+ for (const line of lines) {
100
+ if (line.startsWith('__COMMAND__:')) {
101
+ try {
102
+ const json = line.slice('__COMMAND__:'.length);
103
+ const command = JSON.parse(json);
104
+ this.emit('command', command);
105
+ }
106
+ catch {
107
+ // Invalid JSON, treat as regular output
108
+ remainingLines.push(line);
109
+ }
110
+ }
111
+ else if (line.length > 0 || lines.indexOf(line) < lines.length - 1) {
112
+ remainingLines.push(line);
113
+ }
114
+ }
115
+ // Keep incomplete line in buffer
116
+ const lastLine = remainingLines[remainingLines.length - 1];
117
+ if (lastLine !== undefined && !lastLine.endsWith('\n')) {
118
+ this.stdoutBuffer = lastLine;
119
+ remainingLines.pop();
120
+ }
121
+ else {
122
+ this.stdoutBuffer = '';
123
+ }
124
+ // Emit remaining stdout
125
+ const output = remainingLines.join('\n');
126
+ if (output.length > 0) {
127
+ this.emit('stdout', output);
128
+ }
129
+ }
130
+ }
131
+ /**
132
+ * Manages Python process lifecycle
133
+ */
134
+ export class ProcessManager {
135
+ activeProcesses = new Set();
136
+ preludePath;
137
+ constructor() {
138
+ // Get the directory containing this file
139
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
140
+ this.preludePath = path.join(__dirname, 'prelude', 'rlm_prelude.py');
141
+ }
142
+ /**
143
+ * Spawn a new Python process
144
+ */
145
+ spawn(options) {
146
+ const pythonPath = process.env['PYTHON_PATH'] ?? 'python3';
147
+ const childProcess = spawn(pythonPath, ['-u', this.preludePath], {
148
+ cwd: options.cwd,
149
+ env: {
150
+ ...process.env,
151
+ ...options.env,
152
+ PYTHONUNBUFFERED: '1',
153
+ },
154
+ stdio: ['pipe', 'pipe', 'pipe'],
155
+ });
156
+ const pythonProcess = new PythonProcess(childProcess, options.timeoutMs);
157
+ this.activeProcesses.add(pythonProcess);
158
+ pythonProcess.on('exit', () => {
159
+ this.activeProcesses.delete(pythonProcess);
160
+ });
161
+ return pythonProcess;
162
+ }
163
+ /**
164
+ * Kill a specific process
165
+ */
166
+ kill(process) {
167
+ process.kill();
168
+ this.activeProcesses.delete(process);
169
+ }
170
+ /**
171
+ * Kill all active processes
172
+ */
173
+ killAll() {
174
+ for (const process of this.activeProcesses) {
175
+ process.kill();
176
+ }
177
+ this.activeProcesses.clear();
178
+ }
179
+ /**
180
+ * Get count of active processes
181
+ */
182
+ get activeCount() {
183
+ return this.activeProcesses.size;
184
+ }
185
+ }
186
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../../src/infrastructure/sandbox/process-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { ICodeExecutor, ExecutionContext, ExecutionResult, ValidationResult } from '../../domain/interfaces/code-executor.js';
2
+ /**
3
+ * Configuration for Python executor
4
+ */
5
+ export interface PythonExecutorConfig {
6
+ /** Strict mode for validation (default: true) */
7
+ readonly strictMode?: boolean;
8
+ /** Default timeout in ms (default: 30000) */
9
+ readonly defaultTimeoutMs?: number;
10
+ }
11
+ /**
12
+ * Python code executor implementation
13
+ */
14
+ export declare class PythonExecutor implements ICodeExecutor {
15
+ private readonly validator;
16
+ private readonly processManager;
17
+ private readonly config;
18
+ private currentProcess;
19
+ private pendingQueryResolve;
20
+ private pendingQueryReject;
21
+ constructor(config?: PythonExecutorConfig);
22
+ validate(code: string): ValidationResult;
23
+ execute(code: string, context: ExecutionContext): Promise<ExecutionResult>;
24
+ respondToQuery(response: string): Promise<void>;
25
+ kill(): Promise<void>;
26
+ isReady(): boolean;
27
+ private convertCommand;
28
+ }
29
+ //# sourceMappingURL=python-executor.d.ts.map