nothumanallowed 13.5.130 → 13.5.132

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "13.5.130",
3
+ "version": "13.5.132",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -5308,8 +5308,14 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
5308
5308
  let pkg = {};
5309
5309
  try { pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); } catch(_) {}
5310
5310
  if (!pkg.dependencies) pkg.dependencies = {};
5311
+ // Remove server-side deps that can't run in sandbox
5311
5312
  delete pkg.dependencies.pg;
5312
5313
  delete pkg.dependencies.ioredis;
5314
+ delete pkg.dependencies['pg-pool'];
5315
+ delete pkg.dependencies.redis;
5316
+ delete pkg.dependencies.mongoose;
5317
+ delete pkg.dependencies.mysql2;
5318
+ delete pkg.dependencies.sequelize;
5313
5319
  // Force known-good versions — LLM often generates non-existent patch versions
5314
5320
  pkg.dependencies.express = '^4.19.0';
5315
5321
  pkg.dependencies.bcryptjs = '^2.4.3';
@@ -5320,10 +5326,63 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
5320
5326
  pkg.dependencies.dotenv = '^16.4.0';
5321
5327
  pkg.dependencies.nodemailer = '^6.9.0';
5322
5328
  pkg.dependencies['express-validator'] = '^7.0.1';
5329
+ // Auto-detect any require('pkg') in server JS files and add missing deps
5330
+ const KNOWN_VERSIONS = {
5331
+ 'xss-clean': '^0.1.4', 'morgan': '^1.10.0', 'compression': '^1.7.4',
5332
+ 'multer': '^1.4.5-lts.1', 'uuid': '^9.0.0', 'axios': '^1.6.0',
5333
+ 'lodash': '^4.17.21', 'moment': '^2.30.1', 'dayjs': '^1.11.10',
5334
+ 'joi': '^17.12.0', 'zod': '^3.22.4', 'yup': '^1.3.3',
5335
+ 'stripe': '^14.21.0', 'passport': '^0.7.0', 'passport-local': '^1.0.0',
5336
+ 'passport-jwt': '^4.0.1', 'cookie-parser': '^1.4.6', 'body-parser': '^1.20.2',
5337
+ 'express-session': '^1.18.0', 'connect-flash': '^0.1.1', 'method-override': '^3.0.0',
5338
+ 'serve-static': '^1.15.0', 'path': '0.12.7', 'crypto': '^1.0.1',
5339
+ 'sanitize-html': '^2.12.0', 'dompurify': '^3.0.9', 'validator': '^13.11.0',
5340
+ 'express-mongo-sanitize': '^2.2.0', 'hpp': '^0.2.3', 'xss': '^1.0.14',
5341
+ 'winston': '^3.12.0', 'pino': '^8.19.0', 'chalk': '^5.3.0',
5342
+ 'socket.io': '^4.7.4', 'ws': '^8.16.0', 'ejs': '^3.1.9', 'pug': '^3.0.2',
5343
+ 'handlebars': '^4.7.8', 'nunjucks': '^3.2.4', 'sharp': '^0.33.3',
5344
+ 'qrcode': '^1.5.3', 'pdf-lib': '^1.17.1',
5345
+ };
5346
+ const NODE_BUILTINS = new Set(['fs','path','os','crypto','http','https','net','url','util',
5347
+ 'events','stream','buffer','child_process','process','querystring','readline','assert',
5348
+ 'zlib','dns','tls','cluster','worker_threads','perf_hooks','vm','v8','module',
5349
+ 'string_decoder','timers','punycode','domain','console','sys']);
5350
+ function scanRequires(dir) {
5351
+ const found = new Set();
5352
+ const walk = (d) => {
5353
+ let entries;
5354
+ try { entries = fs.readdirSync(d, { withFileTypes: true }); } catch { return; }
5355
+ for (const e of entries) {
5356
+ if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
5357
+ const full = path.join(d, e.name);
5358
+ if (e.isDirectory()) { walk(full); continue; }
5359
+ if (!e.name.endsWith('.js') && !e.name.endsWith('.mjs') && !e.name.endsWith('.cjs')) continue;
5360
+ let src;
5361
+ try { src = fs.readFileSync(full, 'utf8'); } catch { continue; }
5362
+ const re = /require\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g;
5363
+ let m;
5364
+ while ((m = re.exec(src)) !== null) {
5365
+ const pkg2 = m[1].startsWith('@') ? m[1].split('/').slice(0,2).join('/') : m[1].split('/')[0];
5366
+ if (!NODE_BUILTINS.has(pkg2)) found.add(pkg2);
5367
+ }
5368
+ }
5369
+ };
5370
+ walk(dir);
5371
+ return found;
5372
+ }
5373
+ const detected = scanRequires(sandboxDir);
5374
+ const missing = [];
5375
+ for (const mod of detected) {
5376
+ if (!pkg.dependencies[mod] && !pkg.devDependencies?.[mod]) {
5377
+ pkg.dependencies[mod] = KNOWN_VERSIONS[mod] || 'latest';
5378
+ missing.push(mod);
5379
+ }
5380
+ }
5381
+ if (missing.length > 0) sendLog('🔍 Dipendenze auto-rilevate e aggiunte: ' + missing.join(', '));
5323
5382
  pkg.scripts = pkg.scripts || {};
5324
5383
  pkg.scripts.start = 'node server/index.js';
5325
5384
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2), 'utf8');
5326
- sendLog('📦 package.json ottimizzato per sandbox (rimosso pg, redis)');
5385
+ sendLog('📦 package.json ottimizzato per sandbox (rimosso pg/redis, auto-scan require)');
5327
5386
 
5328
5387
  // Create minimal .env for sandbox
5329
5388
  const envContent = [
@@ -5386,48 +5445,70 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
5386
5445
 
5387
5446
  let _lastMissingModule = null;
5388
5447
  let _lastCrashError = null;
5448
+ let _stderrBuffer = ''; // accumulate full stderr for rich error context
5389
5449
  proc.stdout.on('data', d => { const l = d.toString().trim(); if (l) sendLog(' [server] ' + l); });
5390
5450
  proc.stderr.on('data', d => {
5391
5451
  const raw = d.toString();
5452
+ _stderrBuffer += raw;
5392
5453
  // MODULE_NOT_FOUND
5393
5454
  const modMatch = raw.match(/Cannot find module '([^']+)'/);
5394
5455
  if (modMatch) {
5395
5456
  const missingMod = modMatch[1];
5396
5457
  _lastMissingModule = missingMod;
5397
- _lastCrashError = "Cannot find module '" + missingMod + "'";
5458
+ _lastCrashError = "Cannot find module '" + missingMod + "'\n" + _stderrBuffer.slice(0, 1500);
5398
5459
  sendLog(' ❌ Modulo mancante: ' + missingMod);
5399
5460
  if (!global._wcAutoFixQueue) global._wcAutoFixQueue = [];
5400
5461
  global._wcAutoFixQueue.push({ type: 'module_not_found', module: missingMod, dir: sandboxDir, ts: Date.now() });
5401
5462
  sendLog(' 🤖 Avvio auto-fix...');
5402
5463
  return;
5403
5464
  }
5404
- // TypeError / SyntaxError / ReferenceError — capture for autofix
5465
+ // TypeError / SyntaxError / ReferenceError / Error — capture with full stack
5405
5466
  const crashMatch = raw.match(/^(TypeError|SyntaxError|ReferenceError|Error):\s+(.+)/m);
5406
5467
  if (crashMatch) {
5407
- _lastCrashError = crashMatch[1] + ': ' + crashMatch[2].trim();
5408
- sendLog(' ❌ ' + _lastCrashError);
5468
+ _lastCrashError = crashMatch[1] + ': ' + crashMatch[2].trim() + '\n' + _stderrBuffer.slice(0, 1500);
5469
+ sendLog(' ❌ ' + crashMatch[1] + ': ' + crashMatch[2].trim());
5409
5470
  if (!global._wcAutoFixQueue) global._wcAutoFixQueue = [];
5410
5471
  global._wcAutoFixQueue.push({ type: 'crash_error', error: _lastCrashError, dir: sandboxDir, ts: Date.now() });
5411
5472
  sendLog(' 🤖 Avvio auto-fix...');
5412
5473
  return;
5413
5474
  }
5414
- // Skip node internals noise
5475
+ // Log everything else (including at-lines during crash) for visibility
5415
5476
  const l = raw.trim();
5416
- if (!l || l.startsWith('at ') || l.startsWith('(node:') || l === '^') return;
5477
+ if (!l || l.startsWith('(node:') || l === '^') return;
5417
5478
  sendLog(' [server] ' + l);
5418
5479
  });
5419
5480
 
5420
- // Wait for server to be ready (max 10s)
5481
+ // Wait for server to be ready (max 30s).
5482
+ // If process exits early (crash), report the error immediately so the client
5483
+ // can trigger auto-fix while the SSE connection is still open.
5421
5484
  await new Promise((resolve, reject) => {
5422
5485
  let attempts = 0;
5486
+ const MAX_ATTEMPTS = 60; // 30s at 500ms intervals
5487
+ let crashed = false;
5488
+
5489
+ proc.on('exit', (code) => {
5490
+ if (crashed || code === 0) return;
5491
+ crashed = true;
5492
+ // Give stderr a moment to flush
5493
+ setTimeout(() => {
5494
+ const errMsg = _lastCrashError || (_lastMissingModule ? "Cannot find module '" + _lastMissingModule + "'" : 'Server crashed (exit code ' + code + ')');
5495
+ reject(new Error(errMsg));
5496
+ }, 300);
5497
+ });
5498
+
5423
5499
  const tryConnect = () => {
5424
- const s = netMod.createConnection(freePort, '127.0.0.1');
5425
- s.on('connect', () => { s.destroy(); resolve(); });
5426
- s.on('error', () => {
5427
- s.destroy();
5428
- if (++attempts > 20) reject(new Error(_lastMissingModule ? "Cannot find module '" + _lastMissingModule + "'" : 'Server non risponde dopo 10s'));
5429
- else setTimeout(tryConnect, 500);
5430
- });
5500
+ if (crashed) return;
5501
+ const s = netMod.createConnection(freePort, '127.0.0.1');
5502
+ s.on('connect', () => { s.destroy(); resolve(); });
5503
+ s.on('error', () => {
5504
+ s.destroy();
5505
+ if (crashed) return;
5506
+ if (++attempts > MAX_ATTEMPTS) {
5507
+ reject(new Error(_lastCrashError || (_lastMissingModule ? "Cannot find module '" + _lastMissingModule + "'" : 'Server non risponde dopo 30s')));
5508
+ } else {
5509
+ setTimeout(tryConnect, 500);
5510
+ }
5511
+ });
5431
5512
  };
5432
5513
  setTimeout(tryConnect, 1000);
5433
5514
  });
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '13.5.130';
8
+ export const VERSION = '13.5.132';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11