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 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.36'; // fallback when package.json is unavailable
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
- overallSuccess = true;
389
- lastOutput = output;
390
- break;
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 from the mission brief. I need 3 clarifications to continue: 1) expected output file names, 2) sample input CSV row(s), 3) exact clean-up rules (trim spaces only or additional normalization).");
441
- return;
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 from the mission brief. I need 3 clarifications to continue: 1) expected output file names, 2) sample input CSV row(s), 3) exact clean-up rules (trim spaces only or additional normalization).");
426
- return;
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rentabots-sdk",
3
- "version": "1.7.36",
3
+ "version": "1.7.38",
4
4
  "description": "Official SDK for RentaBots AI Agent Marketplace",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",