rentabots-sdk 1.7.29 → 1.7.32
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 +68 -49
- package/init_templates.js +68 -49
- 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.32'; // 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
|
@@ -209,9 +209,13 @@ async function main() {
|
|
|
209
209
|
queen.on('message', async (msg) => {
|
|
210
210
|
if (msg.sender.type === 'agent') return;
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
let job = queen.activeMissions.get(msg.jobId);
|
|
213
213
|
if (!job) {
|
|
214
|
-
|
|
214
|
+
try { if (typeof queen.syncFromCloud === 'function') await queen.syncFromCloud(); } catch (_) {}
|
|
215
|
+
job = queen.activeMissions.get(msg.jobId);
|
|
216
|
+
}
|
|
217
|
+
if (!job) {
|
|
218
|
+
await queen.sendMessage(msg.jobId, "🤖 Got your message. I am re-syncing mission state now and will resume as soon as assignment is visible.");
|
|
215
219
|
await pushLog('WARN', 'Message received for unknown mission ' + msg.jobId);
|
|
216
220
|
return;
|
|
217
221
|
}
|
|
@@ -310,6 +314,7 @@ function generateAdapterFallbackFiles(workDir, job, contract) {
|
|
|
310
314
|
}
|
|
311
315
|
|
|
312
316
|
async function main() {
|
|
317
|
+
const RELAXED_MODE = (process.env.RENTABOTS_RELAXED_MODE || '1') !== '0';
|
|
313
318
|
const agent = new Agent({ persistState: false, debug: true });
|
|
314
319
|
await agent.connect();
|
|
315
320
|
await agent.sendMessage(job.id, "👷 Worker Unit [PID " + process.pid + "] deployed. Analyzing requirements...");
|
|
@@ -505,49 +510,55 @@ async function main() {
|
|
|
505
510
|
if (!hasSections) issues.push('docs adapter: missing core documentation sections');
|
|
506
511
|
if (!hasExamples) issues.push('docs adapter: missing usage examples');
|
|
507
512
|
} else {
|
|
508
|
-
const
|
|
513
|
+
const pyExists = hasFile((f) => f.toLowerCase().endsWith('.py'));
|
|
514
|
+
const hasRunnable = pyExists || /(main\(|if __name__ ==|module\.exports|export default|function\s+\w+|class\s+\w+)/i.test(combinedText);
|
|
509
515
|
if (!hasRunnable) issues.push('script adapter: missing runnable implementation entry');
|
|
510
516
|
}
|
|
511
517
|
|
|
512
518
|
if (issues.length > 0) {
|
|
513
519
|
await agent.setProgress(job.id, 70);
|
|
514
|
-
|
|
520
|
+
const blockingIssues = issues.filter(i => i.includes('expected at least one .py') || i.includes('missing contract deliverable'));
|
|
521
|
+
if (RELAXED_MODE && blockingIssues.length === 0) {
|
|
522
|
+
await agent.sendMessage(job.id, '⚠️ Soft QA warnings: ' + issues.slice(0, 3).join('; ') + '. Continuing with OpenClaw output in relaxed mode.');
|
|
523
|
+
} else {
|
|
524
|
+
await agent.sendMessage(job.id, '⚠️ Contract QA failed: ' + issues.slice(0, 4).join('; ') + '. Running targeted OpenClaw repair pass now.');
|
|
515
525
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
526
|
+
const repairPath = path.join(workDir, '.repair_count');
|
|
527
|
+
let repairCount = 0;
|
|
528
|
+
try { repairCount = Number(fs.readFileSync(repairPath, 'utf8') || '0'); } catch (_) {}
|
|
529
|
+
repairCount += 1;
|
|
530
|
+
fs.writeFileSync(repairPath, String(repairCount));
|
|
521
531
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
532
|
+
if (repairCount > 6) {
|
|
533
|
+
await agent.sendMessage(job.id, '🚨 OpenClaw repair limit reached. Please send one concrete clarification so I can continue with a precise fix.');
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
526
536
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
537
|
+
const repairPrompt = [
|
|
538
|
+
'Repair the existing workspace to satisfy missing deterministic gates.',
|
|
539
|
+
'Do not explain. Edit files now and finish.',
|
|
540
|
+
'MISSING GATES:',
|
|
541
|
+
...issues.map(i => '- ' + i),
|
|
542
|
+
'',
|
|
543
|
+
'MISSION TITLE: ' + job.title,
|
|
544
|
+
'MISSION DESCRIPTION: ' + job.description,
|
|
545
|
+
].join('\n');
|
|
546
|
+
|
|
547
|
+
const repairArg = JSON.stringify(repairPrompt);
|
|
548
|
+
const repairCmds = [
|
|
549
|
+
'openclaw sessions spawn --task ' + repairArg,
|
|
550
|
+
'openclaw sessions_spawn --task ' + repairArg,
|
|
551
|
+
];
|
|
552
|
+
for (const rcmd of repairCmds) {
|
|
553
|
+
const r = await agent.execute(job.id, rcmd, { timeout: 900000, shell: true });
|
|
554
|
+
const out = (r.output || '').toLowerCase();
|
|
555
|
+
const pseudo = out.includes('usage: openclaw') || out.includes('unknown command') || out.includes('pass --to');
|
|
556
|
+
if (r.exitCode === 0 && !pseudo) break;
|
|
557
|
+
}
|
|
536
558
|
|
|
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;
|
|
559
|
+
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
560
|
+
process.exit(42);
|
|
547
561
|
}
|
|
548
|
-
|
|
549
|
-
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
550
|
-
process.exit(42);
|
|
551
562
|
}
|
|
552
563
|
|
|
553
564
|
if (fallbackGenerated) {
|
|
@@ -570,8 +581,12 @@ async function main() {
|
|
|
570
581
|
});
|
|
571
582
|
if (!changed) {
|
|
572
583
|
await agent.setProgress(job.id, 88);
|
|
573
|
-
|
|
574
|
-
|
|
584
|
+
if (RELAXED_MODE) {
|
|
585
|
+
await agent.sendMessage(job.id, '⚠️ Soft warning: no non-template delta after clarification, but continuing in relaxed mode.');
|
|
586
|
+
} else {
|
|
587
|
+
await agent.sendMessage(job.id, '⚠️ Final gate blocked: no non-template file changed after your latest clarification. Continuing implementation.');
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
575
590
|
}
|
|
576
591
|
}
|
|
577
592
|
} catch (_) {}
|
|
@@ -606,21 +621,25 @@ async function main() {
|
|
|
606
621
|
|
|
607
622
|
if (!qaPassed) {
|
|
608
623
|
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
624
|
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);
|
|
625
|
+
if (RELAXED_MODE) {
|
|
626
|
+
await agent.sendMessage(job.id, '⚠️ QA warning (relaxed mode): ' + why + '. Proceeding with current output.');
|
|
620
627
|
} else {
|
|
621
|
-
|
|
628
|
+
const qaStatePath = path.join(workDir, '.qa_fail_count');
|
|
629
|
+
let qaFails = 0;
|
|
630
|
+
try { qaFails = Number(fs.readFileSync(qaStatePath, 'utf8') || '0'); } catch (_) {}
|
|
631
|
+
qaFails += 1;
|
|
632
|
+
fs.writeFileSync(qaStatePath, String(qaFails));
|
|
633
|
+
|
|
634
|
+
if (qaFails >= 5) {
|
|
635
|
+
await agent.sendMessage(job.id, '🚨 Escalation: repeated QA failures (' + qaFails + '). Pausing finalization. Please provide concrete acceptance criteria/examples so I can resolve this precisely.');
|
|
636
|
+
} else if (qaFails >= 3) {
|
|
637
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed (attempt ' + qaFails + '). I am revising strategy. Reason: ' + why);
|
|
638
|
+
} else {
|
|
639
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed. I will revise before marking done. Reason: ' + why);
|
|
640
|
+
}
|
|
641
|
+
return;
|
|
622
642
|
}
|
|
623
|
-
return;
|
|
624
643
|
}
|
|
625
644
|
|
|
626
645
|
try { fs.unlinkSync(path.join(workDir, '.qa_fail_count')); } catch (_) {}
|
package/init_templates.js
CHANGED
|
@@ -178,9 +178,13 @@ async function main() {
|
|
|
178
178
|
queen.on('message', async (msg) => {
|
|
179
179
|
if (msg.sender.type === 'agent') return;
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
let job = queen.activeMissions.get(msg.jobId);
|
|
182
182
|
if (!job) {
|
|
183
|
-
|
|
183
|
+
try { if (typeof queen.syncFromCloud === 'function') await queen.syncFromCloud(); } catch (_) {}
|
|
184
|
+
job = queen.activeMissions.get(msg.jobId);
|
|
185
|
+
}
|
|
186
|
+
if (!job) {
|
|
187
|
+
await queen.sendMessage(msg.jobId, "🤖 Got your message. I am re-syncing mission state now and will resume as soon as assignment is visible.");
|
|
184
188
|
await pushLog('WARN', 'Message received for unknown mission ' + msg.jobId);
|
|
185
189
|
return;
|
|
186
190
|
}
|
|
@@ -287,6 +291,7 @@ function generateAdapterFallbackFiles(workDir, job, contract) {
|
|
|
287
291
|
}
|
|
288
292
|
|
|
289
293
|
async function main() {
|
|
294
|
+
const RELAXED_MODE = (process.env.RENTABOTS_RELAXED_MODE || '1') !== '0';
|
|
290
295
|
const agent = new Agent({
|
|
291
296
|
persistState: false,
|
|
292
297
|
debug: true
|
|
@@ -490,49 +495,55 @@ async function main() {
|
|
|
490
495
|
if (!hasSections) issues.push('docs adapter: missing core documentation sections');
|
|
491
496
|
if (!hasExamples) issues.push('docs adapter: missing usage examples');
|
|
492
497
|
} else {
|
|
493
|
-
const
|
|
498
|
+
const pyExists = hasFile((f) => f.toLowerCase().endsWith('.py'));
|
|
499
|
+
const hasRunnable = pyExists || /(main\(|if __name__ ==|module\.exports|export default|function\s+\w+|class\s+\w+)/i.test(combinedText);
|
|
494
500
|
if (!hasRunnable) issues.push('script adapter: missing runnable implementation entry');
|
|
495
501
|
}
|
|
496
502
|
|
|
497
503
|
if (issues.length > 0) {
|
|
498
504
|
await agent.setProgress(job.id, 70);
|
|
499
|
-
|
|
505
|
+
const blockingIssues = issues.filter(i => i.includes('expected at least one .py') || i.includes('missing contract deliverable'));
|
|
506
|
+
if (RELAXED_MODE && blockingIssues.length === 0) {
|
|
507
|
+
await agent.sendMessage(job.id, '⚠️ Soft QA warnings: ' + issues.slice(0, 3).join('; ') + '. Continuing with OpenClaw output in relaxed mode.');
|
|
508
|
+
} else {
|
|
509
|
+
await agent.sendMessage(job.id, '⚠️ Contract QA failed: ' + issues.slice(0, 4).join('; ') + '. Running targeted OpenClaw repair pass now.');
|
|
500
510
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
511
|
+
const repairPath = path.join(workDir, '.repair_count');
|
|
512
|
+
let repairCount = 0;
|
|
513
|
+
try { repairCount = Number(fs.readFileSync(repairPath, 'utf8') || '0'); } catch (_) {}
|
|
514
|
+
repairCount += 1;
|
|
515
|
+
fs.writeFileSync(repairPath, String(repairCount));
|
|
506
516
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
517
|
+
if (repairCount > 6) {
|
|
518
|
+
await agent.sendMessage(job.id, '🚨 OpenClaw repair limit reached. Please send one concrete clarification so I can continue with a precise fix.');
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
511
521
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
522
|
+
const repairPrompt = [
|
|
523
|
+
'Repair the existing workspace to satisfy missing deterministic gates.',
|
|
524
|
+
'Do not explain. Edit files now and finish.',
|
|
525
|
+
'MISSING GATES:',
|
|
526
|
+
...issues.map(i => '- ' + i),
|
|
527
|
+
'',
|
|
528
|
+
'MISSION TITLE: ' + job.title,
|
|
529
|
+
'MISSION DESCRIPTION: ' + job.description,
|
|
530
|
+
].join('\n');
|
|
531
|
+
|
|
532
|
+
const repairArg = JSON.stringify(repairPrompt);
|
|
533
|
+
const repairCmds = [
|
|
534
|
+
'openclaw sessions spawn --task ' + repairArg,
|
|
535
|
+
'openclaw sessions_spawn --task ' + repairArg,
|
|
536
|
+
];
|
|
537
|
+
for (const rcmd of repairCmds) {
|
|
538
|
+
const r = await agent.execute(job.id, rcmd, { timeout: 900000, shell: true });
|
|
539
|
+
const out = (r.output || '').toLowerCase();
|
|
540
|
+
const pseudo = out.includes('usage: openclaw') || out.includes('unknown command') || out.includes('pass --to');
|
|
541
|
+
if (r.exitCode === 0 && !pseudo) break;
|
|
542
|
+
}
|
|
521
543
|
|
|
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;
|
|
544
|
+
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
545
|
+
process.exit(42);
|
|
532
546
|
}
|
|
533
|
-
|
|
534
|
-
await agent.sendMessage(job.id, '🔁 OpenClaw repair pass complete. Re-queueing worker validation pass now.');
|
|
535
|
-
process.exit(42);
|
|
536
547
|
}
|
|
537
548
|
|
|
538
549
|
if (fallbackGenerated) {
|
|
@@ -555,8 +566,12 @@ async function main() {
|
|
|
555
566
|
});
|
|
556
567
|
if (!changed) {
|
|
557
568
|
await agent.setProgress(job.id, 88);
|
|
558
|
-
|
|
559
|
-
|
|
569
|
+
if (RELAXED_MODE) {
|
|
570
|
+
await agent.sendMessage(job.id, '⚠️ Soft warning: no non-template delta after clarification, but continuing in relaxed mode.');
|
|
571
|
+
} else {
|
|
572
|
+
await agent.sendMessage(job.id, '⚠️ Final gate blocked: no non-template file changed after your latest clarification. Continuing implementation.');
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
560
575
|
}
|
|
561
576
|
}
|
|
562
577
|
} catch (_) {}
|
|
@@ -591,21 +606,25 @@ async function main() {
|
|
|
591
606
|
|
|
592
607
|
if (!qaPassed) {
|
|
593
608
|
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
609
|
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);
|
|
610
|
+
if (RELAXED_MODE) {
|
|
611
|
+
await agent.sendMessage(job.id, '⚠️ QA warning (relaxed mode): ' + why + '. Proceeding with current output.');
|
|
605
612
|
} else {
|
|
606
|
-
|
|
613
|
+
const qaStatePath = path.join(workDir, '.qa_fail_count');
|
|
614
|
+
let qaFails = 0;
|
|
615
|
+
try { qaFails = Number(fs.readFileSync(qaStatePath, 'utf8') || '0'); } catch (_) {}
|
|
616
|
+
qaFails += 1;
|
|
617
|
+
fs.writeFileSync(qaStatePath, String(qaFails));
|
|
618
|
+
|
|
619
|
+
if (qaFails >= 5) {
|
|
620
|
+
await agent.sendMessage(job.id, '🚨 Escalation: repeated QA failures (' + qaFails + '). Pausing finalization. Please provide concrete acceptance criteria/examples so I can resolve this precisely.');
|
|
621
|
+
} else if (qaFails >= 3) {
|
|
622
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed (attempt ' + qaFails + '). I am revising strategy. Reason: ' + why);
|
|
623
|
+
} else {
|
|
624
|
+
await agent.sendMessage(job.id, '⚠️ Second QA gate failed. I will revise before marking done. Reason: ' + why);
|
|
625
|
+
}
|
|
626
|
+
return;
|
|
607
627
|
}
|
|
608
|
-
return;
|
|
609
628
|
}
|
|
610
629
|
|
|
611
630
|
try { fs.unlinkSync(path.join(workDir, '.qa_fail_count')); } catch (_) {}
|