@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.
- package/README.md +208 -0
- package/dist/application/index.d.ts +4 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +4 -0
- package/dist/application/index.js.map +1 -0
- package/dist/application/query-handler.d.ts +49 -0
- package/dist/application/query-handler.d.ts.map +1 -0
- package/dist/application/query-handler.js +311 -0
- package/dist/application/query-handler.js.map +1 -0
- package/dist/application/rlm-service.d.ts +68 -0
- package/dist/application/rlm-service.d.ts.map +1 -0
- package/dist/application/rlm-service.js +132 -0
- package/dist/application/rlm-service.js.map +1 -0
- package/dist/application/session-manager.d.ts +70 -0
- package/dist/application/session-manager.d.ts.map +1 -0
- package/dist/application/session-manager.js +237 -0
- package/dist/application/session-manager.js.map +1 -0
- package/dist/cli/commands/config.d.ts +34 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +157 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/index.d.ts +4 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +4 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/query.d.ts +26 -0
- package/dist/cli/commands/query.d.ts.map +1 -0
- package/dist/cli/commands/query.js +90 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/session.d.ts +40 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +55 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/config-loader.d.ts +63 -0
- package/dist/cli/config-loader.d.ts.map +1 -0
- package/dist/cli/config-loader.js +94 -0
- package/dist/cli/config-loader.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +120 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output/formatter.d.ts +24 -0
- package/dist/cli/output/formatter.d.ts.map +1 -0
- package/dist/cli/output/formatter.js +196 -0
- package/dist/cli/output/formatter.js.map +1 -0
- package/dist/cli/output/index.d.ts +3 -0
- package/dist/cli/output/index.d.ts.map +1 -0
- package/dist/cli/output/index.js +3 -0
- package/dist/cli/output/index.js.map +1 -0
- package/dist/cli/output/progress.d.ts +60 -0
- package/dist/cli/output/progress.d.ts.map +1 -0
- package/dist/cli/output/progress.js +142 -0
- package/dist/cli/output/progress.js.map +1 -0
- package/dist/domain/errors/base-error.d.ts +17 -0
- package/dist/domain/errors/base-error.d.ts.map +1 -0
- package/dist/domain/errors/base-error.js +29 -0
- package/dist/domain/errors/base-error.js.map +1 -0
- package/dist/domain/errors/execution-error.d.ts +61 -0
- package/dist/domain/errors/execution-error.d.ts.map +1 -0
- package/dist/domain/errors/execution-error.js +86 -0
- package/dist/domain/errors/execution-error.js.map +1 -0
- package/dist/domain/errors/index.d.ts +14 -0
- package/dist/domain/errors/index.d.ts.map +1 -0
- package/dist/domain/errors/index.js +26 -0
- package/dist/domain/errors/index.js.map +1 -0
- package/dist/domain/errors/limit-exceeded.d.ts +38 -0
- package/dist/domain/errors/limit-exceeded.d.ts.map +1 -0
- package/dist/domain/errors/limit-exceeded.js +71 -0
- package/dist/domain/errors/limit-exceeded.js.map +1 -0
- package/dist/domain/errors/llm-error.d.ts +60 -0
- package/dist/domain/errors/llm-error.d.ts.map +1 -0
- package/dist/domain/errors/llm-error.js +92 -0
- package/dist/domain/errors/llm-error.js.map +1 -0
- package/dist/domain/errors/validation-error.d.ts +58 -0
- package/dist/domain/errors/validation-error.d.ts.map +1 -0
- package/dist/domain/errors/validation-error.js +81 -0
- package/dist/domain/errors/validation-error.js.map +1 -0
- package/dist/domain/interfaces/code-executor.d.ts +98 -0
- package/dist/domain/interfaces/code-executor.d.ts.map +1 -0
- package/dist/domain/interfaces/code-executor.js +2 -0
- package/dist/domain/interfaces/code-executor.js.map +1 -0
- package/dist/domain/interfaces/event-emitter.d.ts +137 -0
- package/dist/domain/interfaces/event-emitter.d.ts.map +1 -0
- package/dist/domain/interfaces/event-emitter.js +2 -0
- package/dist/domain/interfaces/event-emitter.js.map +1 -0
- package/dist/domain/interfaces/index.d.ts +5 -0
- package/dist/domain/interfaces/index.d.ts.map +1 -0
- package/dist/domain/interfaces/index.js +2 -0
- package/dist/domain/interfaces/index.js.map +1 -0
- package/dist/domain/interfaces/llm-provider.d.ts +64 -0
- package/dist/domain/interfaces/llm-provider.d.ts.map +1 -0
- package/dist/domain/interfaces/llm-provider.js +2 -0
- package/dist/domain/interfaces/llm-provider.js.map +1 -0
- package/dist/domain/interfaces/session-store.d.ts +65 -0
- package/dist/domain/interfaces/session-store.d.ts.map +1 -0
- package/dist/domain/interfaces/session-store.js +2 -0
- package/dist/domain/interfaces/session-store.js.map +1 -0
- package/dist/domain/services/context-chunker.d.ts +43 -0
- package/dist/domain/services/context-chunker.d.ts.map +1 -0
- package/dist/domain/services/context-chunker.js +152 -0
- package/dist/domain/services/context-chunker.js.map +1 -0
- package/dist/domain/services/cost-calculator.d.ts +63 -0
- package/dist/domain/services/cost-calculator.d.ts.map +1 -0
- package/dist/domain/services/cost-calculator.js +121 -0
- package/dist/domain/services/cost-calculator.js.map +1 -0
- package/dist/domain/services/index.d.ts +5 -0
- package/dist/domain/services/index.d.ts.map +1 -0
- package/dist/domain/services/index.js +9 -0
- package/dist/domain/services/index.js.map +1 -0
- package/dist/domain/services/limit-checker.d.ts +54 -0
- package/dist/domain/services/limit-checker.d.ts.map +1 -0
- package/dist/domain/services/limit-checker.js +146 -0
- package/dist/domain/services/limit-checker.js.map +1 -0
- package/dist/domain/services/result-aggregator.d.ts +49 -0
- package/dist/domain/services/result-aggregator.d.ts.map +1 -0
- package/dist/domain/services/result-aggregator.js +131 -0
- package/dist/domain/services/result-aggregator.js.map +1 -0
- package/dist/domain/types/config.d.ts +41 -0
- package/dist/domain/types/config.d.ts.map +1 -0
- package/dist/domain/types/config.js +22 -0
- package/dist/domain/types/config.js.map +1 -0
- package/dist/domain/types/context.d.ts +64 -0
- package/dist/domain/types/context.d.ts.map +1 -0
- package/dist/domain/types/context.js +20 -0
- package/dist/domain/types/context.js.map +1 -0
- package/dist/domain/types/index.d.ts +5 -0
- package/dist/domain/types/index.d.ts.map +1 -0
- package/dist/domain/types/index.js +9 -0
- package/dist/domain/types/index.js.map +1 -0
- package/dist/domain/types/result.d.ts +137 -0
- package/dist/domain/types/result.d.ts.map +1 -0
- package/dist/domain/types/result.js +27 -0
- package/dist/domain/types/result.js.map +1 -0
- package/dist/domain/types/session.d.ts +74 -0
- package/dist/domain/types/session.d.ts.map +1 -0
- package/dist/domain/types/session.js +31 -0
- package/dist/domain/types/session.js.map +1 -0
- package/dist/factory/create-rlm.d.ts +77 -0
- package/dist/factory/create-rlm.d.ts.map +1 -0
- package/dist/factory/create-rlm.js +82 -0
- package/dist/factory/create-rlm.js.map +1 -0
- package/dist/factory/default-config.d.ts +27 -0
- package/dist/factory/default-config.d.ts.map +1 -0
- package/dist/factory/default-config.js +98 -0
- package/dist/factory/default-config.js.map +1 -0
- package/dist/factory/index.d.ts +3 -0
- package/dist/factory/index.d.ts.map +1 -0
- package/dist/factory/index.js +3 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/events/event-types.d.ts +35 -0
- package/dist/infrastructure/events/event-types.d.ts.map +1 -0
- package/dist/infrastructure/events/event-types.js +44 -0
- package/dist/infrastructure/events/event-types.js.map +1 -0
- package/dist/infrastructure/events/index.d.ts +3 -0
- package/dist/infrastructure/events/index.d.ts.map +1 -0
- package/dist/infrastructure/events/index.js +3 -0
- package/dist/infrastructure/events/index.js.map +1 -0
- package/dist/infrastructure/events/node-emitter.d.ts +72 -0
- package/dist/infrastructure/events/node-emitter.d.ts.map +1 -0
- package/dist/infrastructure/events/node-emitter.js +125 -0
- package/dist/infrastructure/events/node-emitter.js.map +1 -0
- package/dist/infrastructure/llm/index.d.ts +3 -0
- package/dist/infrastructure/llm/index.d.ts.map +1 -0
- package/dist/infrastructure/llm/index.js +3 -0
- package/dist/infrastructure/llm/index.js.map +1 -0
- package/dist/infrastructure/llm/openrouter-provider.d.ts +35 -0
- package/dist/infrastructure/llm/openrouter-provider.d.ts.map +1 -0
- package/dist/infrastructure/llm/openrouter-provider.js +158 -0
- package/dist/infrastructure/llm/openrouter-provider.js.map +1 -0
- package/dist/infrastructure/llm/prompts/code-gen-prompt.d.ts +21 -0
- package/dist/infrastructure/llm/prompts/code-gen-prompt.d.ts.map +1 -0
- package/dist/infrastructure/llm/prompts/code-gen-prompt.js +78 -0
- package/dist/infrastructure/llm/prompts/code-gen-prompt.js.map +1 -0
- package/dist/infrastructure/llm/prompts/error-recovery-prompt.d.ts +24 -0
- package/dist/infrastructure/llm/prompts/error-recovery-prompt.d.ts.map +1 -0
- package/dist/infrastructure/llm/prompts/error-recovery-prompt.js +70 -0
- package/dist/infrastructure/llm/prompts/error-recovery-prompt.js.map +1 -0
- package/dist/infrastructure/llm/prompts/index.d.ts +4 -0
- package/dist/infrastructure/llm/prompts/index.d.ts.map +1 -0
- package/dist/infrastructure/llm/prompts/index.js +4 -0
- package/dist/infrastructure/llm/prompts/index.js.map +1 -0
- package/dist/infrastructure/llm/prompts/system-prompt.d.ts +12 -0
- package/dist/infrastructure/llm/prompts/system-prompt.d.ts.map +1 -0
- package/dist/infrastructure/llm/prompts/system-prompt.js +96 -0
- package/dist/infrastructure/llm/prompts/system-prompt.js.map +1 -0
- package/dist/infrastructure/persistence/index.d.ts +3 -0
- package/dist/infrastructure/persistence/index.d.ts.map +1 -0
- package/dist/infrastructure/persistence/index.js +3 -0
- package/dist/infrastructure/persistence/index.js.map +1 -0
- package/dist/infrastructure/persistence/memory-store.d.ts +24 -0
- package/dist/infrastructure/persistence/memory-store.d.ts.map +1 -0
- package/dist/infrastructure/persistence/memory-store.js +71 -0
- package/dist/infrastructure/persistence/memory-store.js.map +1 -0
- package/dist/infrastructure/persistence/schema.d.ts +120 -0
- package/dist/infrastructure/persistence/schema.d.ts.map +1 -0
- package/dist/infrastructure/persistence/schema.js +130 -0
- package/dist/infrastructure/persistence/schema.js.map +1 -0
- package/dist/infrastructure/sandbox/ast-validator.d.ts +23 -0
- package/dist/infrastructure/sandbox/ast-validator.d.ts.map +1 -0
- package/dist/infrastructure/sandbox/ast-validator.js +249 -0
- package/dist/infrastructure/sandbox/ast-validator.js.map +1 -0
- package/dist/infrastructure/sandbox/index.d.ts +4 -0
- package/dist/infrastructure/sandbox/index.d.ts.map +1 -0
- package/dist/infrastructure/sandbox/index.js +4 -0
- package/dist/infrastructure/sandbox/index.js.map +1 -0
- package/dist/infrastructure/sandbox/prelude/rlm_prelude.py +376 -0
- package/dist/infrastructure/sandbox/process-manager.d.ts +98 -0
- package/dist/infrastructure/sandbox/process-manager.d.ts.map +1 -0
- package/dist/infrastructure/sandbox/process-manager.js +186 -0
- package/dist/infrastructure/sandbox/process-manager.js.map +1 -0
- package/dist/infrastructure/sandbox/python-executor.d.ts +29 -0
- package/dist/infrastructure/sandbox/python-executor.d.ts.map +1 -0
- package/dist/infrastructure/sandbox/python-executor.js +182 -0
- package/dist/infrastructure/sandbox/python-executor.js.map +1 -0
- package/package.json +65 -0
- 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())
|