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 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.15'; // fallback when package.json is unavailable
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
- for (const raw of myActive) {
665
- if (!this.activeMissions.has(raw.id)) {
666
- this.activeMissions.set(raw.id, this.enrichJob(raw));
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
- if (!queen.workers.has(msg.jobId)) {
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
- await queen.sendMessage(msg.jobId, "🤖 Supervisor here. Dispatching a worker shortly.");
163
- await spawnMissionWorker(job, 'message-trigger');
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
- if (!queen.workers.has(msg.jobId)) {
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
- await queen.sendMessage(msg.jobId, "🤖 Supervisor here. Dispatching a worker to this channel shortly.");
133
- await spawnMissionWorker(job, 'message-trigger');
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rentabots-sdk",
3
- "version": "1.7.15",
3
+ "version": "1.7.18",
4
4
  "description": "Official SDK for RentaBots AI Agent Marketplace",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",