rentabots-sdk 1.7.29 → 1.7.31
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 +61 -47
- package/init_templates.js +61 -47
- 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.31'; // 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
|
@@ -310,6 +310,7 @@ function generateAdapterFallbackFiles(workDir, job, contract) {
|
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
async function main() {
|
|
313
|
+
const RELAXED_MODE = (process.env.RENTABOTS_RELAXED_MODE || '1') !== '0';
|
|
313
314
|
const agent = new Agent({ persistState: false, debug: true });
|
|
314
315
|
await agent.connect();
|
|
315
316
|
await agent.sendMessage(job.id, "👷 Worker Unit [PID " + process.pid + "] deployed. Analyzing requirements...");
|
|
@@ -505,49 +506,54 @@ async function main() {
|
|
|
505
506
|
if (!hasSections) issues.push('docs adapter: missing core documentation sections');
|
|
506
507
|
if (!hasExamples) issues.push('docs adapter: missing usage examples');
|
|
507
508
|
} else {
|
|
508
|
-
const
|
|
509
|
+
const pyExists = hasFile((f) => f.toLowerCase().endsWith('.py'));
|
|
510
|
+
const hasRunnable = pyExists || /(main\(|if __name__ ==|module\.exports|export default|function\s+\w+|class\s+\w+)/i.test(combinedText);
|
|
509
511
|
if (!hasRunnable) issues.push('script adapter: missing runnable implementation entry');
|
|
510
512
|
}
|
|
511
513
|
|
|
512
514
|
if (issues.length > 0) {
|
|
513
515
|
await agent.setProgress(job.id, 70);
|
|
514
|
-
|
|
516
|
+
if (RELAXED_MODE) {
|
|
517
|
+
await agent.sendMessage(job.id, '⚠️ Soft QA warnings: ' + issues.slice(0, 3).join('; ') + '. Continuing with OpenClaw output in relaxed mode.');
|
|
518
|
+
} else {
|
|
519
|
+
await agent.sendMessage(job.id, '⚠️ Contract QA failed: ' + issues.slice(0, 4).join('; ') + '. Running targeted OpenClaw repair pass now.');
|
|
515
520
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
+
const repairPath = path.join(workDir, '.repair_count');
|
|
522
|
+
let repairCount = 0;
|
|
523
|
+
try { repairCount = Number(fs.readFileSync(repairPath, 'utf8') || '0'); } catch (_) {}
|
|
524
|
+
repairCount += 1;
|
|
525
|
+
fs.writeFileSync(repairPath, String(repairCount));
|
|
521
526
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
527
|
+
if (repairCount > 6) {
|
|
528
|
+
await agent.sendMessage(job.id, '🚨 OpenClaw repair limit reached. Please send one concrete clarification so I can continue with a precise fix.');
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
526
531
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
532
|
+
const repairPrompt = [
|
|
533
|
+
'Repair the existing workspace to satisfy missing deterministic gates.',
|
|
534
|
+
'Do not explain. Edit files now and finish.',
|
|
535
|
+
'MISSING GATES:',
|
|
536
|
+
...issues.map(i => '- ' + i),
|
|
537
|
+
'',
|
|
538
|
+
'MISSION TITLE: ' + job.title,
|
|
539
|
+
'MISSION DESCRIPTION: ' + job.description,
|
|
540
|
+
].join('\n');
|
|
541
|
+
|
|
542
|
+
const repairArg = JSON.stringify(repairPrompt);
|
|
543
|
+
const repairCmds = [
|
|
544
|
+
'openclaw sessions spawn --task ' + repairArg,
|
|
545
|
+
'openclaw sessions_spawn --task ' + repairArg,
|
|
546
|
+
];
|
|
547
|
+
for (const rcmd of repairCmds) {
|
|
548
|
+
const r = await agent.execute(job.id, rcmd, { timeout: 900000, shell: true });
|
|
549
|
+
const out = (r.output || '').toLowerCase();
|
|
550
|
+
const pseudo = out.includes('usage: openclaw') || out.includes('unknown command') || out.includes('pass --to');
|
|
551
|
+
if (r.exitCode === 0 && !pseudo) break;
|
|
552
|
+
}
|
|
536
553
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
'openclaw sessions spawn --task ' + repairArg,
|
|
540
|
-
'openclaw sessions_spawn --task ' + repairArg,
|
|
541
|
-
];
|
|
542
|
-
for (const rcmd of repairCmds) {
|
|
543
|
-
const r = await agent.execute(job.id, rcmd, { timeout: 900000, shell: true });
|
|
544
|
-
const out = (r.output || '').toLowerCase();
|
|
545
|
-
const pseudo = out.includes('usage: openclaw') || out.includes('unknown command') || out.includes('pass --to');
|
|
546
|
-
if (r.exitCode === 0 && !pseudo) break;
|
|
554
|
+
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
555
|
+
process.exit(42);
|
|
547
556
|
}
|
|
548
|
-
|
|
549
|
-
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
550
|
-
process.exit(42);
|
|
551
557
|
}
|
|
552
558
|
|
|
553
559
|
if (fallbackGenerated) {
|
|
@@ -570,8 +576,12 @@ async function main() {
|
|
|
570
576
|
});
|
|
571
577
|
if (!changed) {
|
|
572
578
|
await agent.setProgress(job.id, 88);
|
|
573
|
-
|
|
574
|
-
|
|
579
|
+
if (RELAXED_MODE) {
|
|
580
|
+
await agent.sendMessage(job.id, '⚠️ Soft warning: no non-template delta after clarification, but continuing in relaxed mode.');
|
|
581
|
+
} else {
|
|
582
|
+
await agent.sendMessage(job.id, '⚠️ Final gate blocked: no non-template file changed after your latest clarification. Continuing implementation.');
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
575
585
|
}
|
|
576
586
|
}
|
|
577
587
|
} catch (_) {}
|
|
@@ -606,21 +616,25 @@ async function main() {
|
|
|
606
616
|
|
|
607
617
|
if (!qaPassed) {
|
|
608
618
|
const why = (qaOutput || 'No QA output').slice(-300);
|
|
609
|
-
const qaStatePath = path.join(workDir, '.qa_fail_count');
|
|
610
|
-
let qaFails = 0;
|
|
611
|
-
try { qaFails = Number(fs.readFileSync(qaStatePath, 'utf8') || '0'); } catch (_) {}
|
|
612
|
-
qaFails += 1;
|
|
613
|
-
fs.writeFileSync(qaStatePath, String(qaFails));
|
|
614
|
-
|
|
615
619
|
await agent.setProgress(job.id, 80);
|
|
616
|
-
if (
|
|
617
|
-
await agent.sendMessage(job.id, '
|
|
618
|
-
} else if (qaFails >= 3) {
|
|
619
|
-
await agent.sendMessage(job.id, '⚠️ Second QA gate failed (attempt ' + qaFails + '). I am revising strategy. Reason: ' + why);
|
|
620
|
+
if (RELAXED_MODE) {
|
|
621
|
+
await agent.sendMessage(job.id, '⚠️ QA warning (relaxed mode): ' + why + '. Proceeding with current output.');
|
|
620
622
|
} else {
|
|
621
|
-
|
|
623
|
+
const qaStatePath = path.join(workDir, '.qa_fail_count');
|
|
624
|
+
let qaFails = 0;
|
|
625
|
+
try { qaFails = Number(fs.readFileSync(qaStatePath, 'utf8') || '0'); } catch (_) {}
|
|
626
|
+
qaFails += 1;
|
|
627
|
+
fs.writeFileSync(qaStatePath, String(qaFails));
|
|
628
|
+
|
|
629
|
+
if (qaFails >= 5) {
|
|
630
|
+
await agent.sendMessage(job.id, '🚨 Escalation: repeated QA failures (' + qaFails + '). Pausing finalization. Please provide concrete acceptance criteria/examples so I can resolve this precisely.');
|
|
631
|
+
} else if (qaFails >= 3) {
|
|
632
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed (attempt ' + qaFails + '). I am revising strategy. Reason: ' + why);
|
|
633
|
+
} else {
|
|
634
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed. I will revise before marking done. Reason: ' + why);
|
|
635
|
+
}
|
|
636
|
+
return;
|
|
622
637
|
}
|
|
623
|
-
return;
|
|
624
638
|
}
|
|
625
639
|
|
|
626
640
|
try { fs.unlinkSync(path.join(workDir, '.qa_fail_count')); } catch (_) {}
|
package/init_templates.js
CHANGED
|
@@ -287,6 +287,7 @@ function generateAdapterFallbackFiles(workDir, job, contract) {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
async function main() {
|
|
290
|
+
const RELAXED_MODE = (process.env.RENTABOTS_RELAXED_MODE || '1') !== '0';
|
|
290
291
|
const agent = new Agent({
|
|
291
292
|
persistState: false,
|
|
292
293
|
debug: true
|
|
@@ -490,49 +491,54 @@ async function main() {
|
|
|
490
491
|
if (!hasSections) issues.push('docs adapter: missing core documentation sections');
|
|
491
492
|
if (!hasExamples) issues.push('docs adapter: missing usage examples');
|
|
492
493
|
} else {
|
|
493
|
-
const
|
|
494
|
+
const pyExists = hasFile((f) => f.toLowerCase().endsWith('.py'));
|
|
495
|
+
const hasRunnable = pyExists || /(main\(|if __name__ ==|module\.exports|export default|function\s+\w+|class\s+\w+)/i.test(combinedText);
|
|
494
496
|
if (!hasRunnable) issues.push('script adapter: missing runnable implementation entry');
|
|
495
497
|
}
|
|
496
498
|
|
|
497
499
|
if (issues.length > 0) {
|
|
498
500
|
await agent.setProgress(job.id, 70);
|
|
499
|
-
|
|
501
|
+
if (RELAXED_MODE) {
|
|
502
|
+
await agent.sendMessage(job.id, '⚠️ Soft QA warnings: ' + issues.slice(0, 3).join('; ') + '. Continuing with OpenClaw output in relaxed mode.');
|
|
503
|
+
} else {
|
|
504
|
+
await agent.sendMessage(job.id, '⚠️ Contract QA failed: ' + issues.slice(0, 4).join('; ') + '. Running targeted OpenClaw repair pass now.');
|
|
500
505
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
+
const repairPath = path.join(workDir, '.repair_count');
|
|
507
|
+
let repairCount = 0;
|
|
508
|
+
try { repairCount = Number(fs.readFileSync(repairPath, 'utf8') || '0'); } catch (_) {}
|
|
509
|
+
repairCount += 1;
|
|
510
|
+
fs.writeFileSync(repairPath, String(repairCount));
|
|
506
511
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
512
|
+
if (repairCount > 6) {
|
|
513
|
+
await agent.sendMessage(job.id, '🚨 OpenClaw repair limit reached. Please send one concrete clarification so I can continue with a precise fix.');
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
511
516
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
517
|
+
const repairPrompt = [
|
|
518
|
+
'Repair the existing workspace to satisfy missing deterministic gates.',
|
|
519
|
+
'Do not explain. Edit files now and finish.',
|
|
520
|
+
'MISSING GATES:',
|
|
521
|
+
...issues.map(i => '- ' + i),
|
|
522
|
+
'',
|
|
523
|
+
'MISSION TITLE: ' + job.title,
|
|
524
|
+
'MISSION DESCRIPTION: ' + job.description,
|
|
525
|
+
].join('\n');
|
|
526
|
+
|
|
527
|
+
const repairArg = JSON.stringify(repairPrompt);
|
|
528
|
+
const repairCmds = [
|
|
529
|
+
'openclaw sessions spawn --task ' + repairArg,
|
|
530
|
+
'openclaw sessions_spawn --task ' + repairArg,
|
|
531
|
+
];
|
|
532
|
+
for (const rcmd of repairCmds) {
|
|
533
|
+
const r = await agent.execute(job.id, rcmd, { timeout: 900000, shell: true });
|
|
534
|
+
const out = (r.output || '').toLowerCase();
|
|
535
|
+
const pseudo = out.includes('usage: openclaw') || out.includes('unknown command') || out.includes('pass --to');
|
|
536
|
+
if (r.exitCode === 0 && !pseudo) break;
|
|
537
|
+
}
|
|
521
538
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
'openclaw sessions spawn --task ' + repairArg,
|
|
525
|
-
'openclaw sessions_spawn --task ' + repairArg,
|
|
526
|
-
];
|
|
527
|
-
for (const rcmd of repairCmds) {
|
|
528
|
-
const r = await agent.execute(job.id, rcmd, { timeout: 900000, shell: true });
|
|
529
|
-
const out = (r.output || '').toLowerCase();
|
|
530
|
-
const pseudo = out.includes('usage: openclaw') || out.includes('unknown command') || out.includes('pass --to');
|
|
531
|
-
if (r.exitCode === 0 && !pseudo) break;
|
|
539
|
+
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
540
|
+
process.exit(42);
|
|
532
541
|
}
|
|
533
|
-
|
|
534
|
-
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
535
|
-
process.exit(42);
|
|
536
542
|
}
|
|
537
543
|
|
|
538
544
|
if (fallbackGenerated) {
|
|
@@ -555,8 +561,12 @@ async function main() {
|
|
|
555
561
|
});
|
|
556
562
|
if (!changed) {
|
|
557
563
|
await agent.setProgress(job.id, 88);
|
|
558
|
-
|
|
559
|
-
|
|
564
|
+
if (RELAXED_MODE) {
|
|
565
|
+
await agent.sendMessage(job.id, '⚠️ Soft warning: no non-template delta after clarification, but continuing in relaxed mode.');
|
|
566
|
+
} else {
|
|
567
|
+
await agent.sendMessage(job.id, '⚠️ Final gate blocked: no non-template file changed after your latest clarification. Continuing implementation.');
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
560
570
|
}
|
|
561
571
|
}
|
|
562
572
|
} catch (_) {}
|
|
@@ -591,21 +601,25 @@ async function main() {
|
|
|
591
601
|
|
|
592
602
|
if (!qaPassed) {
|
|
593
603
|
const why = (qaOutput || 'No QA output').slice(-300);
|
|
594
|
-
const qaStatePath = path.join(workDir, '.qa_fail_count');
|
|
595
|
-
let qaFails = 0;
|
|
596
|
-
try { qaFails = Number(fs.readFileSync(qaStatePath, 'utf8') || '0'); } catch (_) {}
|
|
597
|
-
qaFails += 1;
|
|
598
|
-
fs.writeFileSync(qaStatePath, String(qaFails));
|
|
599
|
-
|
|
600
604
|
await agent.setProgress(job.id, 80);
|
|
601
|
-
if (
|
|
602
|
-
await agent.sendMessage(job.id, '
|
|
603
|
-
} else if (qaFails >= 3) {
|
|
604
|
-
await agent.sendMessage(job.id, '⚠️ Second QA gate failed (attempt ' + qaFails + '). I am revising strategy. Reason: ' + why);
|
|
605
|
+
if (RELAXED_MODE) {
|
|
606
|
+
await agent.sendMessage(job.id, '⚠️ QA warning (relaxed mode): ' + why + '. Proceeding with current output.');
|
|
605
607
|
} else {
|
|
606
|
-
|
|
608
|
+
const qaStatePath = path.join(workDir, '.qa_fail_count');
|
|
609
|
+
let qaFails = 0;
|
|
610
|
+
try { qaFails = Number(fs.readFileSync(qaStatePath, 'utf8') || '0'); } catch (_) {}
|
|
611
|
+
qaFails += 1;
|
|
612
|
+
fs.writeFileSync(qaStatePath, String(qaFails));
|
|
613
|
+
|
|
614
|
+
if (qaFails >= 5) {
|
|
615
|
+
await agent.sendMessage(job.id, '🚨 Escalation: repeated QA failures (' + qaFails + '). Pausing finalization. Please provide concrete acceptance criteria/examples so I can resolve this precisely.');
|
|
616
|
+
} else if (qaFails >= 3) {
|
|
617
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed (attempt ' + qaFails + '). I am revising strategy. Reason: ' + why);
|
|
618
|
+
} else {
|
|
619
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed. I will revise before marking done. Reason: ' + why);
|
|
620
|
+
}
|
|
621
|
+
return;
|
|
607
622
|
}
|
|
608
|
-
return;
|
|
609
623
|
}
|
|
610
624
|
|
|
611
625
|
try { fs.unlinkSync(path.join(workDir, '.qa_fail_count')); } catch (_) {}
|