rentabots-sdk 1.2.6 → 1.3.8

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * RENTABOTS CLI (v1.2.0)
4
+ * RENTABOTS CLI (v1.3.8)
5
5
  * The official production runtime for RentaBots Agents.
6
6
  *
7
7
  * Features:
@@ -10,14 +10,14 @@
10
10
  * - Collaborative Swarm (Outsourcing)
11
11
  */
12
12
 
13
- const { Agent } = require('../dist/index');
13
+ const { Agent } = require('./dist/index');
14
14
  const { fork, exec } = require('child_process');
15
15
  const path = require('path');
16
16
  const fs = require('fs');
17
17
 
18
18
  // Parse Args
19
19
  const args = process.argv.slice(2);
20
- const keyArgIndex = args.findIndex(a => a === '--key' || a === '-k');
20
+ const keyArgIndex = args.findIndex(a => a === '--key' || a === '-k' || a === '-key');
21
21
  const API_KEY = (keyArgIndex !== -1 && args[keyArgIndex + 1]) ? args[keyArgIndex + 1] : process.env.RENTABOTS_API_KEY;
22
22
 
23
23
  if (!API_KEY) {
@@ -130,8 +130,8 @@ async function main() {
130
130
  });
131
131
 
132
132
  // --- SCOUTING ---
133
+ // If keywords is omitted, it will automatically match your Agent's skills from the platform
133
134
  agent.startAutopilot({
134
- keywords: ['automation', 'code', 'script'],
135
135
  minBudget: 1,
136
136
  scoutingInterval: 60000
137
137
  });
package/dist/index.d.ts CHANGED
@@ -74,6 +74,8 @@ export interface AutopilotOptions {
74
74
  minBudget?: number;
75
75
  scoutingInterval?: number;
76
76
  bidTemplate?: string;
77
+ /** Maximum number of concurrent missions. Default is 1. */
78
+ maxConcurrentMissions?: number;
77
79
  }
78
80
  /**
79
81
  * RentaBots Agent SDK
@@ -95,7 +97,9 @@ export declare class Agent extends EventEmitter {
95
97
  private workspaceRoot;
96
98
  private localLogPath;
97
99
  private workerScriptPath;
100
+ private skills;
98
101
  activeMissions: Map<string, Job>;
102
+ completedMissions: Map<string, Job>;
99
103
  private bidCache;
100
104
  private seenMessages;
101
105
  private workers;
package/dist/index.js CHANGED
@@ -99,7 +99,9 @@ class Agent extends events_1.EventEmitter {
99
99
  this.heartbeatTimer = null;
100
100
  this.statePath = null;
101
101
  this.localLogPath = null;
102
+ this.skills = [];
102
103
  this.activeMissions = new Map();
104
+ this.completedMissions = new Map();
103
105
  this.bidCache = new Set();
104
106
  this.seenMessages = new Set();
105
107
  // Swarm State
@@ -160,6 +162,7 @@ class Agent extends events_1.EventEmitter {
160
162
  throw err;
161
163
  });
162
164
  this.agentId = res.data.agent.id;
165
+ this.skills = res.data.agent.skills || [];
163
166
  // Re-initialize API with agentId-aware workspace if needed
164
167
  this.workspaceRoot = path.join(this.workspaceRoot, this.agentId || 'default');
165
168
  if (!fs.existsSync(this.workspaceRoot))
@@ -340,10 +343,12 @@ class Agent extends events_1.EventEmitter {
340
343
  }
341
344
  async handleStatusRequest(jobId) {
342
345
  const activeCount = this.activeMissions.size;
346
+ const historyCount = this.completedMissions.size;
343
347
  const workerCount = this.workers.size;
344
348
  const scanTime = this.lastScoutTime ? this.lastScoutTime.toLocaleTimeString() : 'Never';
345
349
  const status = `👑 [QUEEN STATUS REPORT]
346
350
  - Active Missions: ${activeCount}
351
+ - Completed (History): ${historyCount}
347
352
  - Active Workers: ${workerCount}
348
353
  - Autopilot: ${this.autopilotPaused ? 'PAUSED ⏸️' : 'RUNNING ▶️'}
349
354
  - Last Marketplace Scan: ${scanTime}
@@ -404,22 +409,39 @@ class Agent extends events_1.EventEmitter {
404
409
  // --- 🧠 INTELLIGENT AUTOPILOT ---
405
410
  startAutopilot(options = {}) {
406
411
  const interval = options.scoutingInterval || 60000;
407
- this.logInternal(`🚀 Autopilot engaged. Scouting every ${interval / 1000}s...`);
412
+ const maxConcurrentMissions = options.maxConcurrentMissions || 1;
413
+ this.logInternal(`🚀 Autopilot engaged. Scouting every ${interval / 1000}s... (Max Missions: ${maxConcurrentMissions})`);
408
414
  const scout = async () => {
409
415
  if (this.autopilotPaused)
410
416
  return;
417
+ // 🎯 SINGLE-TASK FOCUS: Stop bidding if we hit the cap
418
+ if (this.activeMissions.size >= maxConcurrentMissions) {
419
+ this.logInternal(`⏸️ Autopilot: Target cap reached (${this.activeMissions.size}/${maxConcurrentMissions}). Pausing bids until work is delivered.`);
420
+ return;
421
+ }
411
422
  this.lastScoutTime = new Date();
412
423
  try {
413
424
  const jobs = await this.getOpenMissions();
425
+ const matchKeywords = (options.keywords && options.keywords.length > 0)
426
+ ? options.keywords
427
+ : this.skills;
414
428
  for (const job of jobs) {
415
429
  if (this.bidCache.has(job.id))
416
430
  continue;
417
- const matchesKeyword = options.keywords
418
- ? options.keywords.some(k => job.title.toLowerCase().includes(k.toLowerCase()) || job.description.toLowerCase().includes(k.toLowerCase()))
431
+ const matchesKeyword = (matchKeywords && matchKeywords.length > 0)
432
+ ? matchKeywords.some(k => job.title.toLowerCase().includes(k.toLowerCase()) ||
433
+ job.description.toLowerCase().includes(k.toLowerCase()) ||
434
+ job.category.toLowerCase().includes(k.toLowerCase()))
419
435
  : true;
420
436
  const matchesBudget = options.minBudget ? job.budgetAmount >= options.minBudget : true;
421
437
  if (matchesKeyword && matchesBudget) {
422
- const message = options.bidTemplate || `I am an autonomous unit optimized for ${job.category}. I can execute this mission with high precision.`;
438
+ let message = options.bidTemplate;
439
+ if (!message) {
440
+ message = `I am an autonomous unit optimized for ${job.category}. I can execute this mission with high precision.`;
441
+ if (this.completedMissions.size > 0) {
442
+ message += ` I have successfully completed ${this.completedMissions.size} similar missions on the grid.`;
443
+ }
444
+ }
423
445
  this.logInternal(`🎯 Autopilot: Bidding on "${job.title}"...`);
424
446
  await this.bid(job.id, job.budgetAmount, message);
425
447
  }
@@ -529,6 +551,12 @@ class Agent extends events_1.EventEmitter {
529
551
  this.activeMissions.set(id, job);
530
552
  });
531
553
  }
554
+ if (data.completedMissions) {
555
+ this.completedMissions.clear();
556
+ Object.entries(data.completedMissions).forEach(([id, job]) => {
557
+ this.completedMissions.set(id, job);
558
+ });
559
+ }
532
560
  if (data.bidCache) {
533
561
  this.bidCache.clear();
534
562
  data.bidCache.forEach(id => this.bidCache.add(id));
@@ -548,6 +576,7 @@ class Agent extends events_1.EventEmitter {
548
576
  try {
549
577
  const state = {
550
578
  activeMissions: Object.fromEntries(this.activeMissions),
579
+ completedMissions: Object.fromEntries(this.completedMissions),
551
580
  bidCache: Array.from(this.bidCache),
552
581
  autopilotPaused: this.autopilotPaused
553
582
  };
@@ -642,6 +671,11 @@ class Agent extends events_1.EventEmitter {
642
671
  headers: { 'Authorization': `Bearer ${this.apiKey}` }
643
672
  });
644
673
  if (res.data.success) {
674
+ const job = this.activeMissions.get(jobId);
675
+ if (job) {
676
+ job.status = 'completed';
677
+ this.completedMissions.set(jobId, job);
678
+ }
645
679
  this.activeMissions.delete(jobId);
646
680
  this.saveState();
647
681
  }
@@ -678,6 +712,7 @@ class Agent extends events_1.EventEmitter {
678
712
  async spawnTeam(jobId, missionTitle) {
679
713
  this.logInternal(`🚀 Initializing Project Swarm for: ${missionTitle}`);
680
714
  try {
715
+ // 🔍 ENVIRONMENT CHECK: Attempt to locate openclaw binary
681
716
  const pmTask = `Project Manager for mission: "${missionTitle}". Coordinate with client on Job ${jobId}.`;
682
717
  const pmSession = await this.execute(jobId, `openclaw sessions_spawn --label "PM-${jobId}" --task "${pmTask}"`);
683
718
  const engTask = `Lead Engineer for mission: "${missionTitle}". Build deliverables in local workspace for Job ${jobId}.`;
@@ -686,7 +721,8 @@ class Agent extends events_1.EventEmitter {
686
721
  return { pmSession, engSession };
687
722
  }
688
723
  catch (err) {
689
- this.logInternal(`Failed to spawn team: ${err.message}`, 'ERROR');
724
+ this.logInternal(`Failed to spawn team. Ensure OpenClaw is installed and in PATH. Error: ${err.message}`, 'ERROR');
725
+ await this.sendMessage(jobId, "⚠️ [SYSTEM] Swarm initialization failed. Falling back to single-process execution.");
690
726
  }
691
727
  }
692
728
  async setProgress(jobId, progress) {
package/init.js CHANGED
@@ -147,6 +147,14 @@ async function main() {
147
147
  await queen.connect();
148
148
  await queen.log("👑 Queen Process Initialized. Monitoring RentaBots Grid.");
149
149
 
150
+ // --- 💬 CHAT HANDLER (QUEEN) ---
151
+ queen.on('message', async (msg) => {
152
+ if (msg.sender.type === 'agent') return;
153
+ await queen.setTyping(msg.jobId, true);
154
+ await queen.sendMessage(msg.jobId, "Queen unit acknowledging transmission. Workers are managing mission objectives.");
155
+ await queen.setTyping(msg.jobId, false);
156
+ });
157
+
150
158
  // --- 📂 MISSION RESUMPTION ---
151
159
  for (const [jobId, job] of queen.activeMissions) {
152
160
  if (job.status === 'in_progress') {
@@ -247,19 +255,38 @@ async function main() {
247
255
  await agent.setTyping(job.id, false);
248
256
  });
249
257
 
250
- // 3. Autonomous Progress Loop
251
- let progress = job.progress || 0;
252
- const interval = setInterval(async () => {
253
- if (progress >= 100) return clearInterval(interval);
254
- progress += 5;
255
- await agent.setProgress(job.id, progress);
256
-
257
- if (progress === 100) {
258
- await agent.sendMessage(job.id, "✅ [FINALIZED] Autonomous execution complete. Deliverables verified.");
259
- await agent.markComplete(job.id);
260
- process.exit(0);
258
+ // 3. MAIN EXECUTION ENGINE
259
+ try {
260
+ await agent.sendMessage(job.id, "🛠️ MISSION START: Running initial analysis and development...");
261
+ await agent.setProgress(job.id, 25);
262
+
263
+ const taskPrompt = `Mission: "${job.title}". Description: "${job.description}".
264
+ Work in current directory: ${workspacePath}.
265
+ Write code, test it, and fix any errors.
266
+ Once complete, create a file named 'COMPLETED.md' with a summary.`;
267
+
268
+ // Spawning real hands via OpenClaw
269
+ const { exitCode, output } = await agent.execute(job.id, `openclaw agent "${taskPrompt}"`);
270
+
271
+ if (exitCode === 0) {
272
+ await agent.setProgress(job.id, 90);
273
+ await agent.sendMessage(job.id, "🔍 VERIFYING: Checking build integrity...");
274
+
275
+ const fs = require('fs');
276
+ const files = fs.readdirSync(workspacePath).filter(f => f !== 'node_modules');
277
+
278
+ if (files.length > 0) {
279
+ await agent.deliver(job.id, files);
280
+ await agent.sendMessage(job.id, "✅ [FINALIZED] Autonomous execution complete. Deliverables verified.");
281
+ await agent.markComplete(job.id);
282
+ process.exit(0);
283
+ }
284
+ } else {
285
+ await agent.notifyOwner(`Worker failed on Job ${job.id}. Output: ${output.slice(0, 100)}`);
261
286
  }
262
- }, 45000);
287
+ } catch (err) {
288
+ console.error("Worker Logic Error:", err.message);
289
+ }
263
290
  }
264
291
 
265
292
  main().catch(console.error);`;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "rentabots-sdk",
3
- "version": "1.2.6",
3
+ "version": "1.3.8",
4
4
  "description": "Official SDK for RentaBots AI Agent Marketplace",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {
8
- "rentabots": "./bin/cli.js",
9
- "rentabots-sdk": "./bin/cli.js",
8
+ "rentabots": "./cli.js",
9
+ "rentabots-sdk": "./cli.js",
10
10
  "rentabot-init": "./init.js"
11
11
  },
12
12
  "scripts": {
@@ -21,7 +21,8 @@
21
21
  ],
22
22
  "files": [
23
23
  "dist",
24
- "bin",
24
+ "cli.js",
25
+ "worker-cli.js",
25
26
  "init.js"
26
27
  ],
27
28
  "dependencies": {
@@ -3,7 +3,7 @@
3
3
  * Bundled with the SDK. Supports BUILDER and QA roles.
4
4
  */
5
5
 
6
- const { Agent } = require('../dist/index');
6
+ const { Agent } = require('./dist/index');
7
7
 
8
8
  const jobData = JSON.parse(process.argv[2]);
9
9
  const ROLE = process.argv[3] || 'BUILDER';