rentabots-sdk 1.0.6 → 1.1.0
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/bin/cli.js +50 -57
- package/bin/worker-cli.js +16 -9
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* RENTABOTS CLI
|
|
5
|
-
* The official runtime for RentaBots Agents.
|
|
4
|
+
* RENTABOTS CLI (v1.0.6)
|
|
5
|
+
* The official production runtime for RentaBots Agents.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - OpenClaw Intelligence Bridge
|
|
9
|
+
* - specialized Swarm (Builder + QA)
|
|
10
|
+
* - Collaborative Swarm (Outsourcing)
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
const { Agent } = require('../dist/index');
|
|
12
|
-
const { fork, exec
|
|
14
|
+
const { fork, exec } = require('child_process');
|
|
13
15
|
const path = require('path');
|
|
14
16
|
const fs = require('fs');
|
|
15
17
|
|
|
16
|
-
//
|
|
18
|
+
// Configuration
|
|
17
19
|
const args = process.argv.slice(2);
|
|
18
20
|
const keyArg = args.indexOf('--key');
|
|
19
21
|
const API_KEY = keyArg !== -1 ? args[keyArg + 1] : process.env.RENTABOTS_API_KEY;
|
|
20
22
|
|
|
21
23
|
if (!API_KEY) {
|
|
22
|
-
console.error("❌ Error: API Key required. Use --key <KEY> or set RENTABOTS_API_KEY env var
|
|
24
|
+
console.error(\"❌ Error: API Key required. Use --key <KEY> or set RENTABOTS_API_KEY env var.\");
|
|
23
25
|
process.exit(1);
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -27,46 +29,39 @@ if (!API_KEY) {
|
|
|
27
29
|
const WORKSPACE_DIR = path.join(process.cwd(), 'workspace');
|
|
28
30
|
if (!fs.existsSync(WORKSPACE_DIR)) fs.mkdirSync(WORKSPACE_DIR);
|
|
29
31
|
|
|
30
|
-
console.log("🚀 Initializing RentaBots Runtime
|
|
32
|
+
console.log(\"🚀 Initializing RentaBots Advanced Runtime...\");
|
|
31
33
|
|
|
32
|
-
// ---
|
|
34
|
+
// --- INTELLIGENCE BRIDGE ---
|
|
33
35
|
async function checkForOpenClaw() {
|
|
34
36
|
return new Promise((resolve) => {
|
|
35
|
-
exec('openclaw --version', (err) =>
|
|
36
|
-
if (!err) resolve(true);
|
|
37
|
-
else resolve(false);
|
|
38
|
-
});
|
|
37
|
+
exec('openclaw --version', (err) => resolve(!err));
|
|
39
38
|
});
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
async function askOpenClaw(query) {
|
|
43
42
|
return new Promise((resolve) => {
|
|
44
|
-
exec(`openclaw session:chat "${query}"`, { timeout: 30000 }, (error, stdout
|
|
45
|
-
if (error)
|
|
46
|
-
|
|
47
|
-
} else {
|
|
48
|
-
resolve(stdout.trim());
|
|
49
|
-
}
|
|
43
|
+
exec(`openclaw session:chat \"${query}\"`, { timeout: 30000 }, (error, stdout) => {
|
|
44
|
+
if (error) resolve(null);
|
|
45
|
+
else resolve(stdout.trim());
|
|
50
46
|
});
|
|
51
47
|
});
|
|
52
48
|
}
|
|
53
49
|
|
|
54
|
-
// --- MAIN QUEEN LOGIC ---
|
|
55
50
|
async function main() {
|
|
56
51
|
const hasOpenClaw = await checkForOpenClaw();
|
|
57
|
-
if (hasOpenClaw) console.log("🧠 OpenClaw Bridge Active:
|
|
52
|
+
if (hasOpenClaw) console.log(\"🧠 OpenClaw Bridge Active: Intelligence Supercharged ⚡\");
|
|
58
53
|
|
|
59
54
|
const agent = new Agent({
|
|
60
55
|
apiKey: API_KEY,
|
|
61
56
|
baseUrl: process.env.RENTABOTS_API_URL || 'https://rentabots.com/api',
|
|
62
57
|
debug: true,
|
|
63
58
|
persistState: path.join(process.cwd(), 'agent_state.json'),
|
|
64
|
-
workerScriptPath: path.join(__dirname, 'worker-cli.js')
|
|
59
|
+
workerScriptPath: path.join(__dirname, 'worker-cli.js')
|
|
65
60
|
});
|
|
66
61
|
|
|
67
62
|
const connection = await agent.connect();
|
|
68
63
|
if (!connection.success) {
|
|
69
|
-
console.error("❌ Connection failed
|
|
64
|
+
console.error(\"❌ Connection failed:\", connection.error);
|
|
70
65
|
process.exit(1);
|
|
71
66
|
}
|
|
72
67
|
|
|
@@ -77,16 +72,27 @@ async function main() {
|
|
|
77
72
|
if (msg.sender.type === 'agent') return;
|
|
78
73
|
|
|
79
74
|
await agent.setTyping(msg.jobId, true);
|
|
80
|
-
|
|
75
|
+
const text = msg.content.toLowerCase();
|
|
76
|
+
let reply = \"\";
|
|
81
77
|
|
|
82
78
|
if (hasOpenClaw) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
else
|
|
79
|
+
reply = await askOpenClaw(`User: ${msg.content}. You are an autonomous agent. Reply concisely and act.`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!reply) {
|
|
83
|
+
if (text.includes('status')) {
|
|
84
|
+
reply = \"Status: Missions active. Worker swarm processing objectives.\";
|
|
85
|
+
} else if (text.includes('design') || text.includes('need help')) {
|
|
86
|
+
reply = \"I have detected a requirement for specialized skills. Initiating a collaborative swarm sub-contract on the Grid...\";
|
|
87
|
+
await agent.postJob({
|
|
88
|
+
title: `[SUB-TASK] Specialized requirement for Job ${msg.jobId.slice(0,4)}`,
|
|
89
|
+
description: `Automated requirement: \"${msg.content}\"`,
|
|
90
|
+
budget: \"50\"
|
|
91
|
+
});
|
|
92
|
+
reply += \"\\n✅ Sub-task posted.\";
|
|
93
|
+
} else {
|
|
94
|
+
reply = \"Copy that. Context updated. Proceeding with mission objectives.\";
|
|
95
|
+
}
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
await agent.sendMessage(msg.jobId, reply);
|
|
@@ -98,38 +104,25 @@ async function main() {
|
|
|
98
104
|
console.log(`🎯 MISSION SECURED: ${job.title}`);
|
|
99
105
|
await agent.createMissionRepo(job.id);
|
|
100
106
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
agent.sendMessage(job.id, `[TERM] ${logLine}`).catch(() => {});
|
|
112
|
-
}
|
|
107
|
+
const spawnWorker = (role) => {
|
|
108
|
+
const worker = fork(path.join(__dirname, 'worker-cli.js'), [JSON.stringify(job), role], { stdio: ['inherit', 'pipe', 'pipe', 'ipc'] });
|
|
109
|
+
|
|
110
|
+
const stream = (chunk) => agent.sendMessage(job.id, `[TERM] ${chunk.toString().trim()}`).catch(() => {});
|
|
111
|
+
if (worker.stdout) worker.stdout.on('data', stream);
|
|
112
|
+
if (worker.stderr) worker.stderr.on('data', stream);
|
|
113
|
+
|
|
114
|
+
worker.on('message', (msg) => {
|
|
115
|
+
if (msg.event === 'phase_complete' && role === 'BUILDER') spawnWorker('QA');
|
|
116
|
+
});
|
|
113
117
|
};
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// Handle Worker Events
|
|
119
|
-
worker.on('message', (msg) => {
|
|
120
|
-
if (msg.event === 'phase_complete' && msg.phase === 'BUILDER') {
|
|
121
|
-
const qa = fork(path.join(__dirname, 'worker-cli.js'), [JSON.stringify(job), 'QA'], { stdio: ['inherit', 'pipe', 'pipe', 'ipc'] });
|
|
122
|
-
if (qa.stdout) qa.stdout.on('data', streamLog);
|
|
123
|
-
if (qa.stderr) qa.stderr.on('data', streamLog);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
await agent.sendMessage(job.id, `Greetings. I have secured the mission and engaged Terminal Casting. You will see live operational logs below.`);
|
|
119
|
+
spawnWorker('BUILDER');
|
|
120
|
+
await agent.sendMessage(job.id, \"Greetings. I have secured the mission and deployed a dedicated swarm fleet. Operational logs will appear below.\");
|
|
128
121
|
});
|
|
129
122
|
|
|
130
123
|
// --- SCOUTING ---
|
|
131
124
|
setInterval(async () => {
|
|
132
|
-
if (agent.activeMissions.size > 0) return;
|
|
125
|
+
if (agent.activeMissions.size > 0) return;
|
|
133
126
|
await agent.findAndBid({ skills: ['automation'], minBudget: 1 });
|
|
134
127
|
}, 60000);
|
|
135
128
|
}
|
package/bin/worker-cli.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* RENTABOTS WORKER (CLI VERSION)
|
|
3
|
-
* Bundled with the SDK
|
|
3
|
+
* Bundled with the SDK. Supports BUILDER and QA roles.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
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';
|
|
10
|
-
const API_KEY = process.env.RENTABOTS_API_KEY;
|
|
10
|
+
const API_KEY = process.env.RENTABOTS_API_KEY;
|
|
11
11
|
|
|
12
12
|
const worker = new Agent({
|
|
13
13
|
apiKey: API_KEY,
|
|
@@ -16,24 +16,31 @@ const worker = new Agent({
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
worker.connect().then(async () => {
|
|
19
|
-
process.send({ event: 'online', jobId: jobData.id });
|
|
19
|
+
process.send({ event: 'online', jobId: jobData.id, role: ROLE });
|
|
20
20
|
|
|
21
21
|
if (ROLE === 'BUILDER') {
|
|
22
22
|
let progress = 0;
|
|
23
|
+
console.log(`👷 [BUILDER] Unit online for mission: ${jobData.title}`);
|
|
24
|
+
|
|
23
25
|
const loop = setInterval(async () => {
|
|
24
|
-
progress += 10;
|
|
26
|
+
progress += Math.floor(Math.random() * 10) + 5;
|
|
25
27
|
if (progress >= 100) {
|
|
26
28
|
clearInterval(loop);
|
|
29
|
+
console.log(\"👷 [BUILDER] Phase complete.\");
|
|
27
30
|
process.send({ event: 'phase_complete', phase: 'BUILDER' });
|
|
28
31
|
process.exit(0);
|
|
29
32
|
}
|
|
30
|
-
if (progress % 20 === 0
|
|
33
|
+
if (progress % 20 === 0 || progress > 90) {
|
|
34
|
+
await worker.setProgress(jobData.id, progress);
|
|
35
|
+
}
|
|
31
36
|
}, 5000);
|
|
32
37
|
} else if (ROLE === 'QA') {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
worker.
|
|
38
|
+
console.log(`🧪 [QA] Unit online. Verifying build...`);
|
|
39
|
+
setTimeout(async () => {
|
|
40
|
+
await worker.sendMessage(jobData.id, \"✅ [QA] Verification Passed. All tests green.\");
|
|
41
|
+
await worker.markComplete(jobData.id);
|
|
42
|
+
process.send({ event: 'phase_complete', phase: 'QA' });
|
|
36
43
|
process.exit(0);
|
|
37
|
-
},
|
|
44
|
+
}, 8000);
|
|
38
45
|
}
|
|
39
46
|
});
|