-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathralph-integration-test.js
More file actions
274 lines (209 loc) · 7.58 KB
/
ralph-integration-test.js
File metadata and controls
274 lines (209 loc) · 7.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/env node
/**
* Ralph-StackMemory Integration Test Script
* Simple CLI to test the integration functionality
*/
import { RalphIntegrationDemo } from '../dist/integrations/ralph/ralph-integration-demo.js';
import { performance } from 'perf_hooks';
async function main() {
const args = process.argv.slice(2);
const command = args[0] || 'demo';
console.log('\n🧪 Ralph-StackMemory Integration Test');
console.log('=====================================\n');
const startTime = performance.now();
try {
switch (command) {
case 'demo':
await runDemo();
break;
case 'quick':
await runQuickTest();
break;
case 'validate':
await runValidation();
break;
default:
showUsage();
return;
}
const endTime = performance.now();
const duration = Math.round(endTime - startTime);
console.log(`\n✅ Test completed successfully in ${duration}ms`);
} catch (error) {
console.error(`\n❌ Test failed: ${error.message}`);
if (process.env.DEBUG) {
console.error('\nDebug info:');
console.error(error.stack);
}
process.exit(1);
}
}
async function runDemo() {
console.log('🎬 Running full integration demo...\n');
const demo = new RalphIntegrationDemo();
await demo.run();
}
async function runQuickTest() {
console.log('⚡ Running quick validation test...\n');
// Import the core classes to test they load correctly
try {
await import('../dist/integrations/ralph/index.js');
console.log('✓ Core bridge class loaded');
const { ContextBudgetManager } = await import('../dist/integrations/ralph/index.js');
console.log('✓ Context budget manager loaded');
const { StateReconciler } = await import('../dist/integrations/ralph/index.js');
console.log('✓ State reconciler loaded');
await import('../dist/integrations/ralph/index.js');
console.log('✓ Iteration lifecycle loaded');
await import('../dist/integrations/ralph/index.js');
console.log('✓ Performance optimizer loaded');
// Test basic instantiation
const budgetManager = new ContextBudgetManager();
const tokenEstimate = budgetManager.estimateTokens('Hello, world!');
console.log(`✓ Token estimation working: ${tokenEstimate} tokens`);
new StateReconciler();
console.log('✓ State reconciler instantiated');
console.log('\n🎯 All core components validated successfully!');
} catch (error) {
throw new Error(`Component loading failed: ${error.message}`);
}
}
async function runValidation() {
console.log('🔍 Running detailed validation...\n');
// Test context budget manager
await testContextBudgetManager();
// Test state reconciler
await testStateReconciler();
// Test performance optimizer
await testPerformanceOptimizer();
console.log('\n✨ All validation tests passed!');
}
async function testContextBudgetManager() {
console.log('📊 Testing Context Budget Manager...');
const { ContextBudgetManager } = await import('../dist/integrations/ralph/index.js');
const manager = new ContextBudgetManager({
maxTokens: 100,
compressionEnabled: true
});
// Test token estimation
const shortText = 'Short text';
const longText = 'This is a much longer piece of text that should have more tokens estimated for it than the shorter version above.';
const shortTokens = manager.estimateTokens(shortText);
const longTokens = manager.estimateTokens(longText);
if (longTokens <= shortTokens) {
throw new Error('Token estimation not working correctly');
}
// Test empty text
const emptyTokens = manager.estimateTokens('');
if (emptyTokens !== 0) {
throw new Error('Empty text should have 0 tokens');
}
console.log(' ✓ Token estimation working correctly');
// Test usage tracking
const usage = manager.getUsage();
if (typeof usage.used !== 'number' || typeof usage.available !== 'number') {
throw new Error('Usage tracking not working');
}
console.log(' ✓ Usage tracking functional');
}
async function testStateReconciler() {
console.log('🔄 Testing State Reconciler...');
const { StateReconciler } = await import('../dist/integrations/ralph/index.js');
const reconciler = new StateReconciler({
precedence: ['git', 'files', 'memory'],
conflictResolution: 'automatic'
});
// Test conflict detection
const sources = [
{
type: 'git',
state: { iteration: 5, status: 'running' },
timestamp: Date.now(),
confidence: 0.9
},
{
type: 'files',
state: { iteration: 5, status: 'running' },
timestamp: Date.now(),
confidence: 0.95
}
];
const conflicts = reconciler.detectConflicts(sources);
if (conflicts.length !== 0) {
throw new Error('Should not detect conflicts in matching sources');
}
console.log(' ✓ Conflict detection working');
// Test state sources
const gitState = await reconciler.getGitState();
const fileState = await reconciler.getFileState();
const memoryState = await reconciler.getMemoryState('test-loop');
if (gitState.type !== 'git' || fileState.type !== 'files' || memoryState.type !== 'memory') {
throw new Error('State source types incorrect');
}
console.log(' ✓ State source loading functional');
}
async function testPerformanceOptimizer() {
console.log('⚡ Testing Performance Optimizer...');
const { PerformanceOptimizer } = await import('../dist/integrations/ralph/index.js');
const optimizer = new PerformanceOptimizer({
asyncSaves: true,
compressionLevel: 1,
cacheEnabled: true
});
// Test metrics
const metrics = optimizer.getMetrics();
const requiredMetrics = ['iterationTime', 'contextLoadTime', 'stateSaveTime', 'memoryUsage', 'tokenCount', 'cacheHitRate'];
for (const metric of requiredMetrics) {
if (typeof metrics[metric] !== 'number') {
throw new Error(`Missing or invalid metric: ${metric}`);
}
}
console.log(' ✓ Performance metrics available');
// Test compression
const testData = { message: 'Hello, world!', array: [1, 2, 3, 4, 5] };
const compressed = await optimizer.compressData(testData);
if (compressed.compressed !== true) {
throw new Error('Data compression not working');
}
const decompressed = await optimizer.decompressData(compressed);
if (JSON.stringify(decompressed) !== JSON.stringify(testData)) {
throw new Error('Data decompression failed');
}
console.log(' ✓ Compression/decompression working');
// Cleanup
optimizer.cleanup();
}
function showUsage() {
console.log(`
Usage: node ralph-integration-test.js [command]
Commands:
demo Run the full integration demonstration (default)
quick Quick validation of core components
validate Detailed validation of all functionality
Examples:
node ralph-integration-test.js
node ralph-integration-test.js quick
DEBUG=1 node ralph-integration-test.js validate
Environment Variables:
DEBUG=1 Show detailed error information
`);
}
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, _promise) => {
console.error('\n💥 Unhandled Promise Rejection:');
console.error(reason);
process.exit(1);
});
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
console.error('\n💥 Uncaught Exception:');
console.error(error.message);
if (process.env.DEBUG) {
console.error(error.stack);
}
process.exit(1);
});
// Run if called directly
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch(console.error);
}