nothumanallowed 13.5.69 → 13.5.71
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 +1 -1
- package/src/commands/ui.mjs +81 -2
- package/src/services/web-ui.mjs +9 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.71",
|
|
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": {
|
package/src/commands/ui.mjs
CHANGED
|
@@ -4086,7 +4086,11 @@ ${completedHeadings ? `## SECTIONS ALREADY WRITTEN (headings only):\n${completed
|
|
|
4086
4086
|
'Connection': 'keep-alive',
|
|
4087
4087
|
'Access-Control-Allow-Origin': '*',
|
|
4088
4088
|
});
|
|
4089
|
-
const
|
|
4089
|
+
const _sbLogLines = [];
|
|
4090
|
+
const sendLog = (msg) => {
|
|
4091
|
+
_sbLogLines.push(msg);
|
|
4092
|
+
res.write(`data: ${JSON.stringify({ type: 'log', msg })}\n\n`);
|
|
4093
|
+
};
|
|
4090
4094
|
const sendReady = (port, dir) => res.write(`data: ${JSON.stringify({ type: 'ready', port, dir })}\n\n`);
|
|
4091
4095
|
const sendError = (msg) => res.write(`data: ${JSON.stringify({ type: 'error', msg })}\n\n`);
|
|
4092
4096
|
|
|
@@ -4274,6 +4278,21 @@ module.exports = { get, set, del, exists };
|
|
|
4274
4278
|
fs.mkdirSync(path.join(sandboxDir, 'server', 'services'), { recursive: true });
|
|
4275
4279
|
fs.writeFileSync(path.join(sandboxDir, 'server', 'services', 'cache.js'), cacheShim, 'utf8');
|
|
4276
4280
|
|
|
4281
|
+
// Validators shim — LLM often generates require('../utils/validators') with helpers that don't exist
|
|
4282
|
+
const validatorsShim = `
|
|
4283
|
+
// NHA WebCraft Sandbox — utils/validators shim
|
|
4284
|
+
function validateEmail(email) { return typeof email === 'string' && /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(email.trim()); }
|
|
4285
|
+
function sanitizeText(str) { return typeof str === 'string' ? str.replace(/<[^>]*>/g, '').trim() : ''; }
|
|
4286
|
+
function validatePassword(pwd) { return typeof pwd === 'string' && pwd.length >= 8; }
|
|
4287
|
+
function validateUsername(u) { return typeof u === 'string' && u.length >= 2 && u.length <= 50; }
|
|
4288
|
+
function validatePhone(p) { return typeof p === 'string' && /^[+]?[\\d\\s\\-().]{7,20}$/.test(p.trim()); }
|
|
4289
|
+
module.exports = { validateEmail, sanitizeText, validatePassword, validateUsername, validatePhone };
|
|
4290
|
+
`;
|
|
4291
|
+
fs.mkdirSync(path.join(sandboxDir, 'server', 'utils'), { recursive: true });
|
|
4292
|
+
if (!fs.existsSync(path.join(sandboxDir, 'server', 'utils', 'validators.js'))) {
|
|
4293
|
+
fs.writeFileSync(path.join(sandboxDir, 'server', 'utils', 'validators.js'), validatorsShim, 'utf8');
|
|
4294
|
+
}
|
|
4295
|
+
|
|
4277
4296
|
// Patch all generated JS files: fix known wrong require() names
|
|
4278
4297
|
// The LLM often uses 'bcrypt' instead of 'bcryptjs', 'pg' instead of nothing, etc.
|
|
4279
4298
|
const requireFixes = [
|
|
@@ -4293,6 +4312,21 @@ module.exports = { get, set, del, exists };
|
|
|
4293
4312
|
[/require\(['"]winston['"]\)/g, "{createLogger:()=>({info:()=>{},error:()=>{},warn:()=>{}}),transports:{Console:function(){}},format:{combine:()=>{},timestamp:()=>{},json:()=>{}}}"],
|
|
4294
4313
|
[/require\(['"]morgan['"]\)/g, "(()=>(r,s,n)=>n())"],
|
|
4295
4314
|
[/require\(['"]compression['"]\)/g, "(()=>(r,s,n)=>n())"],
|
|
4315
|
+
[/require\(['"]express-validator['"]\)/g, "{body:()=>({isEmail:()=>({normalizeEmail:()=>({run:async()=>{}})}),isLength:()=>({run:async()=>{}}),trim:()=>({escape:()=>({run:async()=>{}})}),notEmpty:()=>({run:async()=>{}})}),validationResult:()=>({isEmpty:()=>true,array:()=>[]})}"],
|
|
4316
|
+
[/require\(['"]validator['"]\)/g, "{isEmail:(s)=>/^[^@\\s]+@[^@\\s]+[.][^@\\s]+$/.test(s),escape:(s)=>String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'),trim:(s)=>String(s).trim(),isEmpty:(s)=>!s||!String(s).trim(),isLength:(s,o)=>{ var l=String(s).length; return (!o.min||l>=o.min)&&(!o.max||l<=o.max); }}"],
|
|
4317
|
+
[/require\(['"]handlebars['"]\)/g, "{compile:(t)=>(d)=>t.replace(/\\{\\{([^}]+)\\}\\}/g,(_,k)=>d[k.trim()]||''),registerHelper:()=>{},registerPartial:()=>{}}"],
|
|
4318
|
+
[/require\(['"]express-handlebars['"]\)/g, "{engine:()=>(p,o,cb)=>cb(null,'<html>'+JSON.stringify(o)+'</html>')}"],
|
|
4319
|
+
[/require\(['"]hbs['"]\)/g, "{registerHelper:()=>{},registerPartial:()=>{}}"],
|
|
4320
|
+
[/require\(['"]ejs['"]\)/g, "{render:(t,d)=>t.replace(/<%=([^%]+)%>/g,(_,k)=>d[k.trim()]||''),renderFile:(f,d,o,cb)=>{ if(typeof o==='function'){o(null,'');}else if(cb){cb(null,'');} }}"],
|
|
4321
|
+
[/require\(['"]pug['"]\)/g, "{compile:()=>(d)=>'',renderFile:(f,d,cb)=>cb&&cb(null,'')}"],
|
|
4322
|
+
[/require\(['"]nunjucks['"]\)/g, "{configure:()=>({}),render:(t,d)=>JSON.stringify(d),renderString:(t,d)=>JSON.stringify(d)}"],
|
|
4323
|
+
[/require\(['"]mustache['"]\)/g, "{render:(t,d)=>t.replace(/\\{\\{([^}]+)\\}\\}/g,(_,k)=>d[k.trim()]||'')}"],
|
|
4324
|
+
[/require\(['"]marked['"]\)/g, "{marked:(s)=>s,parse:(s)=>s}"],
|
|
4325
|
+
[/require\(['"]highlight\.js['"]\)/g, "{highlight:(c)=>({value:c}),highlightAuto:(c)=>({value:c})}"],
|
|
4326
|
+
[/require\(['"]nodemailer['"]\)/g, "{createTransport:()=>({sendMail:(o,cb)=>{ if(cb)cb(null,{messageId:'sandbox-'+Date.now()}); return Promise.resolve({messageId:'sandbox'}); }})}"],
|
|
4327
|
+
[/require\(['"]stripe['"]\)/g, "(()=>({customers:{create:async()=>({id:'cus_sandbox'})},paymentIntents:{create:async()=>({id:'pi_sandbox',client_secret:'sandbox_secret'})}}))()"],
|
|
4328
|
+
[/require\(['"]@sendgrid\/mail['"]\)/g, "{setApiKey:()=>{},send:async()=>({statusCode:202})}"],
|
|
4329
|
+
[/require\(['"]twilio['"]\)/g, "(()=>({messages:{create:async()=>({sid:'SM_sandbox'})}}))()"],
|
|
4296
4330
|
[/require\(['"]cookie-parser['"]\)/g, "(()=>(r,s,n)=>{r.cookies=r.cookies||{};n()})"],
|
|
4297
4331
|
[/require\(['"]passport['"]\)/g, "{initialize:()=>(r,s,n)=>n(),session:()=>(r,s,n)=>n(),authenticate:()=>(r,s,n)=>n&&n()}"],
|
|
4298
4332
|
[/require\(['"]express-session['"]\)/g, "(()=>(r,s,n)=>{r.session=r.session||{};n()})"],
|
|
@@ -4313,6 +4347,14 @@ module.exports = { get, set, del, exists };
|
|
|
4313
4347
|
[/require\(['"]\.\.\/\.\.\/config['"]\)/g, "{env:process.env}"],
|
|
4314
4348
|
[/require\(['"]\.\.\/config['"]\)/g, "{env:process.env}"],
|
|
4315
4349
|
[/require\(['"]\.\/config['"]\)/g, "{env:process.env}"],
|
|
4350
|
+
// utils/* — LLM generates helpers that don't exist; redirect to shim
|
|
4351
|
+
[/require\(['"]\.\.\/utils\/validators['"]\)/g, "require('../utils/validators')"],
|
|
4352
|
+
[/require\(['"]\.\/utils\/validators['"]\)/g, "require('./utils/validators')"],
|
|
4353
|
+
[/require\(['"]\.\.\/utils\/validation['"]\)/g, "require('../utils/validators')"],
|
|
4354
|
+
[/require\(['"]\.\.\/helpers\/validators['"]\)/g, "require('../utils/validators')"],
|
|
4355
|
+
[/require\(['"]\.\.\/utils\/helpers['"]\)/g, "{sanitize:(s)=>String(s).trim(),escape:(s)=>String(s).replace(/</g,'<')}"],
|
|
4356
|
+
[/require\(['"]\.\.\/utils\/logger['"]\)/g, "{info:()=>{},error:()=>{},warn:()=>{},debug:()=>{}}"],
|
|
4357
|
+
[/require\(['"]\.\.\/utils\/errors['"]\)/g, "{AppError:class AppError extends Error{constructor(m,s){super(m);this.statusCode=s||500;}}}"],
|
|
4316
4358
|
// rateLimiter: LLM sometimes creates a separate file instead of importing from security.js
|
|
4317
4359
|
[/require\(['"]\.\.\/middleware\/rateLimiter['"]\)/g, "require('../middleware/security')"],
|
|
4318
4360
|
[/require\(['"]\.\/middleware\/rateLimiter['"]\)/g, "require('./middleware/security')"],
|
|
@@ -4468,8 +4510,44 @@ module.exports = { get, set, del, exists };
|
|
|
4468
4510
|
});
|
|
4469
4511
|
|
|
4470
4512
|
sendLog(`✅ Sandbox pronta!`);
|
|
4513
|
+
|
|
4514
|
+
// Write sandbox log to skills/ so the agent can read it as context
|
|
4515
|
+
try {
|
|
4516
|
+
const _nl = '\n';
|
|
4517
|
+
const logTs = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
4518
|
+
const logName = projName + '-' + logTs.replace(/[: ]/g, '-') + '.log';
|
|
4519
|
+
const logsDir = path.join(sandboxDir, 'skills');
|
|
4520
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
4521
|
+
// Keep only last 3 log files to avoid bloat
|
|
4522
|
+
const existing = fs.readdirSync(logsDir).filter(f => f.endsWith('.log') && f.startsWith(projName + '-'));
|
|
4523
|
+
existing.sort().slice(0, -2).forEach(f => { try { fs.unlinkSync(path.join(logsDir, f)); } catch(_) {} });
|
|
4524
|
+
const logContent = '# Sandbox Log — ' + projName + _nl + 'Avviato: ' + logTs + _nl + 'Porta: ' + freePort + _nl + _nl + _sbLogLines.join(_nl);
|
|
4525
|
+
fs.writeFileSync(path.join(logsDir, logName), logContent, 'utf8');
|
|
4526
|
+
// Also update _index.json so the UI knows the type
|
|
4527
|
+
const idxPath = path.join(logsDir, '_index.json');
|
|
4528
|
+
let idx = {};
|
|
4529
|
+
try { idx = JSON.parse(fs.readFileSync(idxPath, 'utf8')); } catch(_) {}
|
|
4530
|
+
idx[logName] = 'log';
|
|
4531
|
+
fs.writeFileSync(idxPath, JSON.stringify(idx), 'utf8');
|
|
4532
|
+
} catch(_) {}
|
|
4533
|
+
|
|
4471
4534
|
sendReady(freePort, sandboxDir);
|
|
4472
4535
|
} catch (e) {
|
|
4536
|
+
// Write error log too
|
|
4537
|
+
try {
|
|
4538
|
+
const _nl = '\n';
|
|
4539
|
+
const logTs = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
4540
|
+
const logName = projName + '-' + logTs.replace(/[: ]/g, '-') + '-ERROR.log';
|
|
4541
|
+
const logsDir = path.join(sandboxDir, 'skills');
|
|
4542
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
4543
|
+
const logContent = '# Sandbox Log — ' + projName + ' [ERRORE]' + _nl + 'Avviato: ' + logTs + _nl + _nl + _sbLogLines.join(_nl) + _nl + _nl + '❌ ERRORE: ' + e.message;
|
|
4544
|
+
fs.writeFileSync(path.join(logsDir, logName), logContent, 'utf8');
|
|
4545
|
+
const idxPath = path.join(logsDir, '_index.json');
|
|
4546
|
+
let idx = {};
|
|
4547
|
+
try { idx = JSON.parse(fs.readFileSync(idxPath, 'utf8')); } catch(_) {}
|
|
4548
|
+
idx[logName] = 'log';
|
|
4549
|
+
fs.writeFileSync(idxPath, JSON.stringify(idx), 'utf8');
|
|
4550
|
+
} catch(_) {}
|
|
4473
4551
|
sendError(e.message);
|
|
4474
4552
|
}
|
|
4475
4553
|
res.end();
|
|
@@ -4548,7 +4626,7 @@ module.exports = { get, set, del, exists };
|
|
|
4548
4626
|
let typeIndex = {};
|
|
4549
4627
|
if (fs.existsSync(indexPath)) { try { typeIndex = JSON.parse(fs.readFileSync(indexPath, 'utf8')); } catch(_) {} }
|
|
4550
4628
|
const defaultType = (n) => n === 'memory.md' ? 'memory' : n === 'liara.md' ? 'provider' : 'skill';
|
|
4551
|
-
const sections = { memory: [], provider: [], skill: [] };
|
|
4629
|
+
const sections = { memory: [], provider: [], skill: [], log: [] };
|
|
4552
4630
|
for (const fname of fs.readdirSync(skillsDir)) {
|
|
4553
4631
|
if (!fname.endsWith('.md')) continue;
|
|
4554
4632
|
try {
|
|
@@ -4563,6 +4641,7 @@ module.exports = { get, set, del, exists };
|
|
|
4563
4641
|
if (sections.memory.length) parts.push('MEMORIA PROGETTO:\n' + sections.memory.join('\n\n'));
|
|
4564
4642
|
if (sections.provider.length) parts.push('ISTRUZIONI MODELLO AI:\n' + sections.provider.join('\n\n'));
|
|
4565
4643
|
if (sections.skill.length) parts.push('SKILLS & PATTERN:\n' + sections.skill.join('\n\n'));
|
|
4644
|
+
if (sections.log && sections.log.length) parts.push('LOG AVVIO SANDBOX (ultimo):\n' + sections.log[sections.log.length - 1]);
|
|
4566
4645
|
if (parts.length) skillsContext = '\n' + parts.join('\n\n') + '\n';
|
|
4567
4646
|
}
|
|
4568
4647
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -6727,11 +6727,11 @@ function wcOpenSandbox() { if (wcState.sandbox.port) window.open('http://127.0.0
|
|
|
6727
6727
|
// ── WebCraft Context Files (Skills / Memory / Provider) ───────────────────────
|
|
6728
6728
|
|
|
6729
6729
|
function wcFileTypeIcon(type) {
|
|
6730
|
-
return type === 'memory' ? '🧠' : type === 'provider' ? '🤖' : '📋';
|
|
6730
|
+
return type === 'memory' ? '🧠' : type === 'provider' ? '🤖' : type === 'log' ? '📄' : '📋';
|
|
6731
6731
|
}
|
|
6732
6732
|
function wcFileTypeBadge(type) {
|
|
6733
|
-
var colors = { memory: '#7c5cbf', provider: '#2a7fff', skill: '#1a7a4a' };
|
|
6734
|
-
var labels = { memory: 'memory', provider: 'provider', skill: 'skill' };
|
|
6733
|
+
var colors = { memory: '#7c5cbf', provider: '#2a7fff', skill: '#1a7a4a', log: '#555' };
|
|
6734
|
+
var labels = { memory: 'memory', provider: 'provider', skill: 'skill', log: 'log' };
|
|
6735
6735
|
return '<span style="font-size:9px;padding:1px 5px;border-radius:3px;background:' + (colors[type]||'#444') + ';color:#fff;margin-left:4px;flex-shrink:0">' + (labels[type]||type) + '</span>';
|
|
6736
6736
|
}
|
|
6737
6737
|
|
|
@@ -6756,14 +6756,16 @@ function wcSkillsPanelHtml() {
|
|
|
6756
6756
|
// Can add new skill only (memory + provider are singletons already in defaults)
|
|
6757
6757
|
var rows = wcSkills.map(function(s, si) {
|
|
6758
6758
|
var isSingleton = s.type === 'memory' || s.type === 'provider';
|
|
6759
|
+
var isLog = s.type === 'log';
|
|
6759
6760
|
var isEmpty = !s.content || s.content.trim() === '';
|
|
6760
6761
|
return '<div style="display:flex;align-items:center;gap:4px;padding:5px 0;border-bottom:1px solid var(--border)">' +
|
|
6761
6762
|
'<span style="font-size:13px;flex-shrink:0">' + wcFileTypeIcon(s.type) + '</span>' +
|
|
6762
|
-
'<span style="font-size:11px;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + wcEsc(s.name) + '</span>' +
|
|
6763
|
+
'<span style="font-size:11px;color:'+(isLog?'var(--dim)':'var(--text)')+';flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="'+wcEsc(s.name)+'">' + wcEsc(s.name) + '</span>' +
|
|
6763
6764
|
wcFileTypeBadge(s.type) +
|
|
6764
|
-
(isEmpty ? '<span title="Vuoto" style="font-size:9px;color:#e09020;flex-shrink:0">⚠</span>' : '') +
|
|
6765
|
-
'<button onclick="wcOpenSkill('+si+')" title="Modifica" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:12px;padding:2px 4px;flex-shrink:0"
|
|
6766
|
-
(!isSingleton ? '<button onclick="wcClearSkill('+si+')" title="Svuota" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:11px;padding:2px 4px;flex-shrink:0">🗑</button>' : '') +
|
|
6765
|
+
(!isLog && isEmpty ? '<span title="Vuoto" style="font-size:9px;color:#e09020;flex-shrink:0">⚠</span>' : '') +
|
|
6766
|
+
'<button onclick="wcOpenSkill('+si+')" title="'+(isLog?'Visualizza log':'Modifica')+'" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:12px;padding:2px 4px;flex-shrink:0">'+(isLog?'👁':'✎')+'</button>' +
|
|
6767
|
+
(!isSingleton && !isLog ? '<button onclick="wcClearSkill('+si+')" title="Svuota" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:11px;padding:2px 4px;flex-shrink:0">🗑</button>' : '') +
|
|
6768
|
+
(isLog ? '<button onclick="wcDeleteSkill('+si+')" title="Elimina log" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:11px;padding:2px 4px;flex-shrink:0">🗑</button>' : '') +
|
|
6767
6769
|
'</div>';
|
|
6768
6770
|
}).join('');
|
|
6769
6771
|
return '<div style="background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:14px">' +
|