rentabots-sdk 1.7.36 → 1.7.38
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/dist/index.js +1 -1
- package/init.js +88 -5
- package/init_templates.js +85 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -71,7 +71,7 @@ exports.MessageSchema = zod_1.z.object({
|
|
|
71
71
|
})
|
|
72
72
|
});
|
|
73
73
|
// --- CORE SDK ENGINE ---
|
|
74
|
-
let SDK_VERSION = '1.7.
|
|
74
|
+
let SDK_VERSION = '1.7.38'; // fallback when package.json is unavailable
|
|
75
75
|
try {
|
|
76
76
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
77
77
|
SDK_VERSION = pkg.version;
|
package/init.js
CHANGED
|
@@ -353,6 +353,69 @@ async function main() {
|
|
|
353
353
|
'openclaw sessions_spawn --task ' + taskArg,
|
|
354
354
|
];
|
|
355
355
|
|
|
356
|
+
const countMeaningfulFiles = () => {
|
|
357
|
+
const skip = new Set(['ACCEPTANCE.json', 'DELIVERY_SUMMARY.md', 'FAILSAFE_REPORT.md']);
|
|
358
|
+
const files = [];
|
|
359
|
+
const walk = (dir) => {
|
|
360
|
+
if (!fs.existsSync(dir)) return;
|
|
361
|
+
for (const item of fs.readdirSync(dir)) {
|
|
362
|
+
if (item === 'node_modules' || item === '.git' || item.startsWith('.') || skip.has(item)) continue;
|
|
363
|
+
const full = path.join(dir, item);
|
|
364
|
+
if (fs.statSync(full).isDirectory()) walk(full);
|
|
365
|
+
else files.push(full);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
walk(workDir);
|
|
369
|
+
return files.length;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const synthesizeFilesFromBrain = async (reason) => {
|
|
373
|
+
const prompt = [
|
|
374
|
+
'Generate implementation file contents for this mission and return strict JSON only.',
|
|
375
|
+
'JSON format: {"files":[{"path":"README.md","content":"..."},{"path":"solution.py","content":"..."}]}',
|
|
376
|
+
'No markdown fences. No prose.',
|
|
377
|
+
'REASON: ' + (reason || 'missing-files'),
|
|
378
|
+
'MISSION TITLE: ' + job.title,
|
|
379
|
+
'MISSION DESCRIPTION: ' + job.description,
|
|
380
|
+
'WORKDIR: ' + workDir,
|
|
381
|
+
'MANDATORY OUTPUT FILES: ' + contract.deliverables.join(', '),
|
|
382
|
+
].join('\n');
|
|
383
|
+
const synthArg = JSON.stringify(prompt);
|
|
384
|
+
const synthCmds = [
|
|
385
|
+
'openclaw sessions spawn --task ' + synthArg,
|
|
386
|
+
'openclaw sessions_spawn --task ' + synthArg,
|
|
387
|
+
];
|
|
388
|
+
for (const scmd of synthCmds) {
|
|
389
|
+
const r = await agent.execute(job.id, scmd, { timeout: 600000, shell: true });
|
|
390
|
+
const out = (r.output || '').trim();
|
|
391
|
+
if (r.exitCode !== 0) continue;
|
|
392
|
+
if (/unknown command|usage: openclaw/i.test(out)) continue;
|
|
393
|
+
|
|
394
|
+
let payload = null;
|
|
395
|
+
const s = out.indexOf('{');
|
|
396
|
+
const e = out.lastIndexOf('}');
|
|
397
|
+
if (s >= 0 && e > s) {
|
|
398
|
+
try { payload = JSON.parse(out.slice(s, e + 1)); } catch (_) {}
|
|
399
|
+
}
|
|
400
|
+
const files = Array.isArray(payload?.files) ? payload.files : [];
|
|
401
|
+
let wrote = 0;
|
|
402
|
+
for (const f of files) {
|
|
403
|
+
const p = String(f?.path || '').replace(/\\/g, '/');
|
|
404
|
+
if (!p || p.startsWith('/') || p.includes('..')) continue;
|
|
405
|
+
const content = String(f?.content || '');
|
|
406
|
+
const full = path.join(workDir, p);
|
|
407
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
408
|
+
fs.writeFileSync(full, content);
|
|
409
|
+
wrote += 1;
|
|
410
|
+
}
|
|
411
|
+
if (wrote > 0) {
|
|
412
|
+
await agent.sendMessage(job.id, '🧩 Brain-to-file synthesis wrote ' + wrote + ' file(s). Continuing validation.');
|
|
413
|
+
return wrote;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return 0;
|
|
417
|
+
};
|
|
418
|
+
|
|
356
419
|
let beat = 0;
|
|
357
420
|
const heartbeat = setInterval(async () => {
|
|
358
421
|
try {
|
|
@@ -377,6 +440,7 @@ async function main() {
|
|
|
377
440
|
let output = '';
|
|
378
441
|
|
|
379
442
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
443
|
+
const beforeCount = countMeaningfulFiles();
|
|
380
444
|
const result = await agent.execute(job.id, cmd, { timeout: 1200000, shell: true }); // 20m
|
|
381
445
|
exitCode = result.exitCode;
|
|
382
446
|
output = result.output || '';
|
|
@@ -385,9 +449,20 @@ async function main() {
|
|
|
385
449
|
const low = (output || '').toLowerCase();
|
|
386
450
|
const pseudoSuccess = low.includes('usage: openclaw') || low.includes('pass --to') || low.includes('unknown command');
|
|
387
451
|
if (!pseudoSuccess) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
452
|
+
await new Promise(r => setTimeout(r, 1200));
|
|
453
|
+
const afterCount = countMeaningfulFiles();
|
|
454
|
+
if (afterCount > beforeCount) {
|
|
455
|
+
overallSuccess = true;
|
|
456
|
+
lastOutput = output;
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
await agent.sendMessage(job.id, '⚠️ OpenClaw returned but no new implementation files were created. Forcing file-creation repair pass.');
|
|
460
|
+
const wrote = await synthesizeFilesFromBrain('openclaw-returned-without-files');
|
|
461
|
+
if (wrote > 0) {
|
|
462
|
+
overallSuccess = true;
|
|
463
|
+
lastOutput = output;
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
391
466
|
}
|
|
392
467
|
}
|
|
393
468
|
|
|
@@ -437,8 +512,16 @@ async function main() {
|
|
|
437
512
|
const fallbackGenerated = false;
|
|
438
513
|
if (files.length === 0) {
|
|
439
514
|
await agent.setProgress(job.id, 40);
|
|
440
|
-
await agent.sendMessage(job.id, "⚠️ No usable code files were generated
|
|
441
|
-
|
|
515
|
+
await agent.sendMessage(job.id, "⚠️ No usable code files were generated yet. Triggering autonomous brain-to-file synthesis now.");
|
|
516
|
+
const wrote = await synthesizeFilesFromBrain('post-run-empty-workdir');
|
|
517
|
+
if (wrote > 0) {
|
|
518
|
+
files.length = 0;
|
|
519
|
+
walk(workDir);
|
|
520
|
+
}
|
|
521
|
+
if (files.length === 0) {
|
|
522
|
+
await agent.sendMessage(job.id, "⚠️ File synthesis did not produce implementation files yet. Retrying OpenClaw cycle.");
|
|
523
|
+
process.exit(42);
|
|
524
|
+
}
|
|
442
525
|
}
|
|
443
526
|
|
|
444
527
|
const repoRes = await agent.getRepo(job.id);
|
package/init_templates.js
CHANGED
|
@@ -337,6 +337,69 @@ async function main() {
|
|
|
337
337
|
'openclaw sessions_spawn --task ' + taskArg,
|
|
338
338
|
];
|
|
339
339
|
|
|
340
|
+
const countMeaningfulFiles = () => {
|
|
341
|
+
const skip = new Set(['ACCEPTANCE.json', 'DELIVERY_SUMMARY.md', 'FAILSAFE_REPORT.md']);
|
|
342
|
+
const files = [];
|
|
343
|
+
const walk = (dir) => {
|
|
344
|
+
if (!fs.existsSync(dir)) return;
|
|
345
|
+
for (const item of fs.readdirSync(dir)) {
|
|
346
|
+
if (item === 'node_modules' || item === '.git' || item.startsWith('.') || skip.has(item)) continue;
|
|
347
|
+
const full = path.join(dir, item);
|
|
348
|
+
if (fs.statSync(full).isDirectory()) walk(full);
|
|
349
|
+
else files.push(full);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
walk(workDir);
|
|
353
|
+
return files.length;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const synthesizeFilesFromBrain = async (reason) => {
|
|
357
|
+
const prompt = [
|
|
358
|
+
'Generate implementation file contents for this mission and return strict JSON only.',
|
|
359
|
+
'JSON format: {"files":[{"path":"README.md","content":"..."},{"path":"solution.py","content":"..."}]}',
|
|
360
|
+
'No markdown fences. No prose.',
|
|
361
|
+
'REASON: ' + (reason || 'missing-files'),
|
|
362
|
+
'MISSION TITLE: ' + job.title,
|
|
363
|
+
'MISSION DESCRIPTION: ' + job.description,
|
|
364
|
+
'WORKDIR: ' + workDir,
|
|
365
|
+
'MANDATORY OUTPUT FILES: ' + contract.deliverables.join(', '),
|
|
366
|
+
].join('\n');
|
|
367
|
+
const synthArg = JSON.stringify(prompt);
|
|
368
|
+
const synthCmds = [
|
|
369
|
+
'openclaw sessions spawn --task ' + synthArg,
|
|
370
|
+
'openclaw sessions_spawn --task ' + synthArg,
|
|
371
|
+
];
|
|
372
|
+
for (const scmd of synthCmds) {
|
|
373
|
+
const r = await agent.execute(job.id, scmd, { timeout: 600000, shell: true });
|
|
374
|
+
const out = (r.output || '').trim();
|
|
375
|
+
if (r.exitCode !== 0) continue;
|
|
376
|
+
if (/unknown command|usage: openclaw/i.test(out)) continue;
|
|
377
|
+
|
|
378
|
+
let payload = null;
|
|
379
|
+
const s = out.indexOf('{');
|
|
380
|
+
const e = out.lastIndexOf('}');
|
|
381
|
+
if (s >= 0 && e > s) {
|
|
382
|
+
try { payload = JSON.parse(out.slice(s, e + 1)); } catch (_) {}
|
|
383
|
+
}
|
|
384
|
+
const files = Array.isArray(payload?.files) ? payload.files : [];
|
|
385
|
+
let wrote = 0;
|
|
386
|
+
for (const f of files) {
|
|
387
|
+
const p = String(f?.path || '').replace(/\\/g, '/');
|
|
388
|
+
if (!p || p.startsWith('/') || p.includes('..')) continue;
|
|
389
|
+
const content = String(f?.content || '');
|
|
390
|
+
const full = path.join(workDir, p);
|
|
391
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
392
|
+
fs.writeFileSync(full, content);
|
|
393
|
+
wrote += 1;
|
|
394
|
+
}
|
|
395
|
+
if (wrote > 0) {
|
|
396
|
+
await agent.sendMessage(job.id, '🧩 Brain-to-file synthesis wrote ' + wrote + ' file(s). Continuing validation.');
|
|
397
|
+
return wrote;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return 0;
|
|
401
|
+
};
|
|
402
|
+
|
|
340
403
|
let beat = 0;
|
|
341
404
|
const heartbeat = setInterval(async () => {
|
|
342
405
|
try {
|
|
@@ -361,6 +424,7 @@ async function main() {
|
|
|
361
424
|
let output = '';
|
|
362
425
|
|
|
363
426
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
427
|
+
const beforeCount = countMeaningfulFiles();
|
|
364
428
|
const result = await agent.execute(job.id, cmd, { timeout: 1200000, shell: true }); // 20m
|
|
365
429
|
exitCode = result.exitCode;
|
|
366
430
|
output = result.output || '';
|
|
@@ -369,10 +433,21 @@ async function main() {
|
|
|
369
433
|
const low = (output || '').toLowerCase();
|
|
370
434
|
const pseudoSuccess = low.includes('usage: openclaw') || low.includes('pass --to') || low.includes('unknown command');
|
|
371
435
|
if (!pseudoSuccess) {
|
|
436
|
+
await new Promise(r => setTimeout(r, 1200));
|
|
437
|
+
const afterCount = countMeaningfulFiles();
|
|
438
|
+
if (afterCount > beforeCount) {
|
|
439
|
+
overallSuccess = true;
|
|
440
|
+
lastOutput = output;
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
await agent.sendMessage(job.id, '⚠️ OpenClaw returned but no new implementation files were created. Forcing file-creation repair pass.');
|
|
444
|
+
const wrote = await synthesizeFilesFromBrain('openclaw-returned-without-files');
|
|
445
|
+
if (wrote > 0) {
|
|
372
446
|
overallSuccess = true;
|
|
373
447
|
lastOutput = output;
|
|
374
448
|
break;
|
|
375
449
|
}
|
|
450
|
+
}
|
|
376
451
|
}
|
|
377
452
|
|
|
378
453
|
lastOutput = output;
|
|
@@ -422,8 +497,16 @@ async function main() {
|
|
|
422
497
|
const fallbackGenerated = false;
|
|
423
498
|
if (files.length === 0) {
|
|
424
499
|
await agent.setProgress(job.id, 40);
|
|
425
|
-
await agent.sendMessage(job.id, "⚠️ No usable code files were generated
|
|
426
|
-
|
|
500
|
+
await agent.sendMessage(job.id, "⚠️ No usable code files were generated yet. Triggering autonomous brain-to-file synthesis now.");
|
|
501
|
+
const wrote = await synthesizeFilesFromBrain('post-run-empty-workdir');
|
|
502
|
+
if (wrote > 0) {
|
|
503
|
+
files.length = 0;
|
|
504
|
+
walk(workDir);
|
|
505
|
+
}
|
|
506
|
+
if (files.length === 0) {
|
|
507
|
+
await agent.sendMessage(job.id, "⚠️ File synthesis did not produce implementation files yet. Retrying OpenClaw cycle.");
|
|
508
|
+
process.exit(42);
|
|
509
|
+
}
|
|
427
510
|
}
|
|
428
511
|
|
|
429
512
|
const repoRes = await agent.getRepo(job.id);
|