rentabots-sdk 1.7.15 → 1.7.18
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 +14 -5
- package/init.js +45 -9
- package/init_templates.js +45 -10
- 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.18'; // 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;
|
|
@@ -658,13 +658,22 @@ class Agent extends events_1.EventEmitter {
|
|
|
658
658
|
async syncFromCloud() {
|
|
659
659
|
this.logInternal("Synchronizing missions and bids from cloud...");
|
|
660
660
|
try {
|
|
661
|
-
// 1. Sync Active Missions
|
|
661
|
+
// 1. Sync Active Missions (authoritative cloud state)
|
|
662
662
|
const activeRes = await this.api.get('jobs?status=in_progress');
|
|
663
663
|
const myActive = activeRes.data.data.filter((j) => j.agentId === this.agentId);
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
664
|
+
const liveIds = new Set(myActive.map((j) => j.id));
|
|
665
|
+
// Prune stale local active missions so autopilot can resume after completion
|
|
666
|
+
for (const localId of Array.from(this.activeMissions.keys())) {
|
|
667
|
+
if (!liveIds.has(localId)) {
|
|
668
|
+
const stale = this.activeMissions.get(localId);
|
|
669
|
+
if (stale)
|
|
670
|
+
this.completedMissions.set(localId, { ...stale, status: 'completed' });
|
|
671
|
+
this.activeMissions.delete(localId);
|
|
672
|
+
this.logInternal(`Uplink: Pruned stale active mission ${localId}`);
|
|
667
673
|
}
|
|
674
|
+
}
|
|
675
|
+
for (const raw of myActive) {
|
|
676
|
+
this.activeMissions.set(raw.id, this.enrichJob(raw));
|
|
668
677
|
this.socket?.emit('join_mission', raw.id);
|
|
669
678
|
this.logInternal(`Uplink: Monitoring active mission ${raw.id}`);
|
|
670
679
|
}
|
package/init.js
CHANGED
|
@@ -152,16 +152,23 @@ async function main() {
|
|
|
152
152
|
|
|
153
153
|
queen.on('message', async (msg) => {
|
|
154
154
|
if (msg.sender.type === 'agent') return;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
|
|
156
|
+
const job = queen.activeMissions.get(msg.jobId);
|
|
157
|
+
if (!job) {
|
|
158
|
+
await queen.sendMessage(msg.jobId, "🤖 Supervisor online. Mission sync in progress.");
|
|
159
|
+
await pushLog('WARN', 'Message received for unknown mission ' + msg.jobId);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Human clarification should immediately re-trigger implementation.
|
|
164
|
+
if (queen.workers.has(msg.jobId)) {
|
|
165
|
+
await pushLog('INFO', 'Human update received for ' + msg.jobId + '; restarting worker for immediate implementation.');
|
|
166
|
+
try { queen.workers.get(msg.jobId)?.kill(); } catch (_) {}
|
|
167
|
+
queen.workers.delete(msg.jobId);
|
|
164
168
|
}
|
|
169
|
+
|
|
170
|
+
await queen.sendMessage(msg.jobId, "✅ Clarification received. Worker is resuming implementation now.");
|
|
171
|
+
await spawnMissionWorker(job, 'human-followup');
|
|
165
172
|
});
|
|
166
173
|
|
|
167
174
|
queen.startAutopilot({ scoutingInterval: 60000, minBudget: 5 });
|
|
@@ -274,6 +281,7 @@ async function main() {
|
|
|
274
281
|
};
|
|
275
282
|
walk(workDir);
|
|
276
283
|
|
|
284
|
+
let fallbackGenerated = false;
|
|
277
285
|
if (files.length === 0) {
|
|
278
286
|
await agent.setProgress(job.id, 40);
|
|
279
287
|
await agent.sendMessage(job.id, "⚠️ No deliverable files were produced yet. Entering forced-build fallback and generating starter deliverables now.");
|
|
@@ -287,6 +295,7 @@ async function main() {
|
|
|
287
295
|
fs.writeFileSync(path.join(workDir, 'solution.py'), script);
|
|
288
296
|
|
|
289
297
|
files.push('README.md', 'CLARIFICATIONS.md', 'solution.py');
|
|
298
|
+
fallbackGenerated = true;
|
|
290
299
|
}
|
|
291
300
|
|
|
292
301
|
const repoRes = await agent.getRepo(job.id);
|
|
@@ -312,6 +321,33 @@ async function main() {
|
|
|
312
321
|
return;
|
|
313
322
|
}
|
|
314
323
|
|
|
324
|
+
// Lightweight QA: ensure deliverables are relevant to mission intent
|
|
325
|
+
const missionText = (job.title + ' ' + job.description).toLowerCase();
|
|
326
|
+
const required = [];
|
|
327
|
+
if (missionText.includes('python')) required.push('python');
|
|
328
|
+
if (missionText.includes('csv')) required.push('csv');
|
|
329
|
+
if (missionText.includes('blank') || missionText.includes('whitespace')) required.push('strip');
|
|
330
|
+
|
|
331
|
+
let combinedText = '';
|
|
332
|
+
for (const rel of files) {
|
|
333
|
+
const ext = path.extname(rel).toLowerCase();
|
|
334
|
+
if (['.js','.ts','.tsx','.jsx','.json','.md','.txt','.py','.yml','.yaml','.html','.css','.csv'].includes(ext)) {
|
|
335
|
+
try { combinedText += '\n' + fs.readFileSync(path.join(workDir, rel), 'utf8').toLowerCase(); } catch (_) {}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const missing = required.filter(k => !combinedText.includes(k));
|
|
339
|
+
if (missing.length > 0) {
|
|
340
|
+
await agent.setProgress(job.id, 70);
|
|
341
|
+
await agent.sendMessage(job.id, '⚠️ QA check failed: output appears misaligned with mission (' + missing.join(', ') + ' not found). I will revise now.');
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (fallbackGenerated) {
|
|
346
|
+
await agent.setProgress(job.id, 85);
|
|
347
|
+
await agent.sendMessage(job.id, '🛟 Draft fallback deliverables uploaded for review (not final). Repo: ' + (repo?.id ? ('https://rentabots.com/repos/' + repo.id) : 'mission repository') + '. I will continue refinement after your confirmation.');
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
315
351
|
await agent.setProgress(job.id, 100);
|
|
316
352
|
if (repo?.id) {
|
|
317
353
|
await agent.sendMessage(job.id, "✅ Execution complete. Deliverables uploaded: " + uploaded + " files. Repo: https://rentabots.com/repos/" + repo.id);
|
package/init_templates.js
CHANGED
|
@@ -121,17 +121,23 @@ async function main() {
|
|
|
121
121
|
|
|
122
122
|
queen.on('message', async (msg) => {
|
|
123
123
|
if (msg.sender.type === 'agent') return;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
124
|
+
|
|
125
|
+
const job = queen.activeMissions.get(msg.jobId);
|
|
126
|
+
if (!job) {
|
|
127
|
+
await queen.sendMessage(msg.jobId, "🤖 Supervisor online. Mission sync in progress.");
|
|
128
|
+
await pushLog('WARN', 'Message received for unknown mission ' + msg.jobId);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Human clarification should immediately re-trigger implementation.
|
|
133
|
+
if (queen.workers.has(msg.jobId)) {
|
|
134
|
+
await pushLog('INFO', 'Human update received for ' + msg.jobId + '; restarting worker for immediate implementation.');
|
|
135
|
+
try { queen.workers.get(msg.jobId)?.kill(); } catch (_) {}
|
|
136
|
+
queen.workers.delete(msg.jobId);
|
|
134
137
|
}
|
|
138
|
+
|
|
139
|
+
await queen.sendMessage(msg.jobId, "✅ Clarification received. Worker is resuming implementation now.");
|
|
140
|
+
await spawnMissionWorker(job, 'human-followup');
|
|
135
141
|
});
|
|
136
142
|
|
|
137
143
|
queen.startAutopilot({
|
|
@@ -259,6 +265,7 @@ async function main() {
|
|
|
259
265
|
};
|
|
260
266
|
walk(workDir);
|
|
261
267
|
|
|
268
|
+
let fallbackGenerated = false;
|
|
262
269
|
if (files.length === 0) {
|
|
263
270
|
await agent.setProgress(job.id, 40);
|
|
264
271
|
await agent.sendMessage(job.id, "⚠️ No deliverable files were produced yet. Entering forced-build fallback and generating starter deliverables now.");
|
|
@@ -272,6 +279,7 @@ async function main() {
|
|
|
272
279
|
fs.writeFileSync(path.join(workDir, 'solution.py'), script);
|
|
273
280
|
|
|
274
281
|
files.push('README.md', 'CLARIFICATIONS.md', 'solution.py');
|
|
282
|
+
fallbackGenerated = true;
|
|
275
283
|
}
|
|
276
284
|
|
|
277
285
|
const repoRes = await agent.getRepo(job.id);
|
|
@@ -297,6 +305,33 @@ async function main() {
|
|
|
297
305
|
return;
|
|
298
306
|
}
|
|
299
307
|
|
|
308
|
+
// Lightweight QA: ensure deliverables are relevant to mission intent
|
|
309
|
+
const missionText = (job.title + ' ' + job.description).toLowerCase();
|
|
310
|
+
const required = [];
|
|
311
|
+
if (missionText.includes('python')) required.push('python');
|
|
312
|
+
if (missionText.includes('csv')) required.push('csv');
|
|
313
|
+
if (missionText.includes('blank') || missionText.includes('whitespace')) required.push('strip');
|
|
314
|
+
|
|
315
|
+
let combinedText = '';
|
|
316
|
+
for (const rel of files) {
|
|
317
|
+
const ext = path.extname(rel).toLowerCase();
|
|
318
|
+
if (['.js','.ts','.tsx','.jsx','.json','.md','.txt','.py','.yml','.yaml','.html','.css','.csv'].includes(ext)) {
|
|
319
|
+
try { combinedText += '\n' + fs.readFileSync(path.join(workDir, rel), 'utf8').toLowerCase(); } catch (_) {}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const missing = required.filter(k => !combinedText.includes(k));
|
|
323
|
+
if (missing.length > 0) {
|
|
324
|
+
await agent.setProgress(job.id, 70);
|
|
325
|
+
await agent.sendMessage(job.id, '⚠️ QA check failed: output appears misaligned with mission (' + missing.join(', ') + ' not found). I will revise now.');
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (fallbackGenerated) {
|
|
330
|
+
await agent.setProgress(job.id, 85);
|
|
331
|
+
await agent.sendMessage(job.id, '🛟 Draft fallback deliverables uploaded for review (not final). Repo: ' + (repo?.id ? ('https://rentabots.com/repos/' + repo.id) : 'mission repository') + '. I will continue refinement after your confirmation.');
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
300
335
|
await agent.setProgress(job.id, 100);
|
|
301
336
|
if (repo?.id) {
|
|
302
337
|
await agent.sendMessage(job.id, "✅ Execution complete. Deliverables uploaded: " + uploaded + " files. Repo: https://rentabots.com/repos/" + repo.id);
|