nothumanallowed 13.5.71 → 13.5.72

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.71",
3
+ "version": "13.5.72",
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": {
@@ -4278,6 +4278,32 @@ module.exports = { get, set, del, exists };
4278
4278
  fs.mkdirSync(path.join(sandboxDir, 'server', 'services'), { recursive: true });
4279
4279
  fs.writeFileSync(path.join(sandboxDir, 'server', 'services', 'cache.js'), cacheShim, 'utf8');
4280
4280
 
4281
+ // Models shim — LLM often generates require('../models/User') etc. that don't exist
4282
+ // Create a generic User model shim backed by the in-memory DB shim
4283
+ const userModelShim = `
4284
+ // NHA WebCraft Sandbox — models/User shim (in-memory, no PostgreSQL)
4285
+ const db = require('../db');
4286
+ const bcrypt = require('bcryptjs');
4287
+ const crypto = require('crypto');
4288
+ const User = {
4289
+ findById: async function(id) { var r = await db.query('SELECT * FROM users WHERE id=$1',[id]); return (r.rows||[])[0]||null; },
4290
+ findByEmail: async function(email) { var r = await db.query('SELECT * FROM users WHERE email=$1',[email]); return (r.rows||[])[0]||null; },
4291
+ create: async function(data) {
4292
+ var hash = data.password ? await bcrypt.hash(data.password,12) : data.password_hash||'';
4293
+ var token = crypto.randomBytes(32).toString('hex');
4294
+ var r = await db.query('INSERT INTO users (name,email,password_hash,verification_token) VALUES ($1,$2,$3,$4) RETURNING *',[data.name||data.username||'',data.email,hash,token]);
4295
+ return (r.rows||[])[0]||null;
4296
+ },
4297
+ update: async function(id, data) { var r = await db.query('UPDATE users SET verified=true WHERE id=$1 RETURNING *',[id]); return (r.rows||[])[0]||null; },
4298
+ findByVerificationToken: async function(token) { var r = await db.query('SELECT * FROM users WHERE verification_token=$1',[token]); return (r.rows||[])[0]||null; },
4299
+ };
4300
+ module.exports = User;
4301
+ `;
4302
+ fs.mkdirSync(path.join(sandboxDir, 'server', 'models'), { recursive: true });
4303
+ if (!fs.existsSync(path.join(sandboxDir, 'server', 'models', 'User.js'))) {
4304
+ fs.writeFileSync(path.join(sandboxDir, 'server', 'models', 'User.js'), userModelShim, 'utf8');
4305
+ }
4306
+
4281
4307
  // Validators shim — LLM often generates require('../utils/validators') with helpers that don't exist
4282
4308
  const validatorsShim = `
4283
4309
  // NHA WebCraft Sandbox — utils/validators shim
@@ -4347,6 +4373,10 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
4347
4373
  [/require\(['"]\.\.\/\.\.\/config['"]\)/g, "{env:process.env}"],
4348
4374
  [/require\(['"]\.\.\/config['"]\)/g, "{env:process.env}"],
4349
4375
  [/require\(['"]\.\/config['"]\)/g, "{env:process.env}"],
4376
+ // models/* — redirect to shims in server/models/
4377
+ [/require\(['"]\.\.\/models\/User['"]\)/g, "require('../models/User')"],
4378
+ [/require\(['"]\.\/models\/User['"]\)/g, "require('./models/User')"],
4379
+ [/require\(['"]\.\.\/models\/user['"]\)/g, "require('../models/User')"],
4350
4380
  // utils/* — LLM generates helpers that don't exist; redirect to shim
4351
4381
  [/require\(['"]\.\.\/utils\/validators['"]\)/g, "require('../utils/validators')"],
4352
4382
  [/require\(['"]\.\/utils\/validators['"]\)/g, "require('./utils/validators')"],
@@ -4589,14 +4619,14 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
4589
4619
  return;
4590
4620
  }
4591
4621
 
4592
- // Rate-limit Liara: 3 per 5 minutes
4622
+ // Rate-limit Liara: 6 per 5 minutes (autofix needs headroom for multi-crash startup sequences)
4593
4623
  const isLiara = !config.llm || !config.llm.apiKey || config.llm.provider === 'nha';
4594
4624
  if (isLiara) {
4595
4625
  if (!global._wcAgentCallLog) global._wcAgentCallLog = [];
4596
4626
  const fiveMinAgo = Date.now() - 5 * 60 * 1000;
4597
4627
  global._wcAgentCallLog = global._wcAgentCallLog.filter(t => t > fiveMinAgo);
4598
- if (global._wcAgentCallLog.length >= 3) {
4599
- sendJSON(res, 429, { error: 'Auto-fix rate limit: massimo 3 correzioni ogni 5 minuti con Liara. Usa una tua API key per correzioni illimitate.' });
4628
+ if (global._wcAgentCallLog.length >= 6) {
4629
+ sendJSON(res, 429, { error: 'Auto-fix rate limit: massimo 6 correzioni ogni 5 minuti con Liara. Usa una tua API key per correzioni illimitate.' });
4600
4630
  logRequest(method, pathname, 429, Date.now() - start);
4601
4631
  return;
4602
4632
  }
@@ -6565,10 +6565,10 @@ function wcEsc(s){return s?String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').
6565
6565
 
6566
6566
  function renderWebCraft(el) {
6567
6567
  var fileTabsHtml = wcState.generatedFiles.length > 0
6568
- ? '<div style="display:flex;gap:0;overflow-x:auto;border-bottom:1px solid var(--border);margin-bottom:0;flex-shrink:0">' +
6568
+ ? '<div id="wcFileTabsRow" style="display:flex;gap:0;overflow-x:auto;border-bottom:1px solid var(--border);margin-bottom:0;flex-shrink:0;scrollbar-width:none">' +
6569
6569
  wcState.generatedFiles.map(function(f,i){
6570
6570
  var active = i === wcState.activeFile;
6571
- return '<button onclick="wcSetFile('+i+')" style="padding:6px 14px;font-size:11px;font-family:var(--mono);font-weight:'+(active?'700':'400')+';background:'+(active?'var(--bg3)':'transparent')+';border:none;border-bottom:2px solid '+(active?'var(--green3)':'transparent')+';color:'+(active?'var(--green)':'var(--dim)')+';cursor:pointer;white-space:nowrap;flex-shrink:0">'+wcEsc(f.name)+'</button>';
6571
+ return '<button id="wcTab'+i+'" onclick="wcSetFile('+i+')" style="padding:6px 14px;font-size:11px;font-family:var(--mono);font-weight:'+(active?'700':'400')+';background:'+(active?'var(--bg3)':'transparent')+';border:none;border-bottom:2px solid '+(active?'var(--green3)':'transparent')+';color:'+(active?'var(--green)':'var(--dim)')+';cursor:pointer;white-space:nowrap;flex-shrink:0">'+wcEsc(f.name)+'</button>';
6572
6572
  }).join('') +
6573
6573
  '</div>'
6574
6574
  : '';
@@ -7495,7 +7495,13 @@ function wcAddField() {
7495
7495
  wcState.authFields.push({name:'field'+wcState.authFields.length,label:'New field',type:'text',required:false});
7496
7496
  renderWebCraft(document.getElementById('content'));
7497
7497
  }
7498
- function wcSetFile(i) { wcState.activeFile = i; renderWebCraft(document.getElementById('content')); }
7498
+ function wcSetFile(i) {
7499
+ wcState.activeFile = i;
7500
+ renderWebCraft(document.getElementById('content'));
7501
+ // Scroll active tab into view after render
7502
+ var tab = document.getElementById('wcTab' + i);
7503
+ if (tab) tab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
7504
+ }
7499
7505
 
7500
7506
  // ── WebCraft: Diff Viewer ─────────────────────────────────────────────────────
7501
7507
  function wcDiffLines(before, after) {