nothumanallowed 13.5.60 → 13.5.62
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 +7 -2
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +91 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.62",
|
|
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
|
@@ -4225,7 +4225,10 @@ function sentinelMiddleware(req, res, next) {
|
|
|
4225
4225
|
}
|
|
4226
4226
|
next();
|
|
4227
4227
|
}
|
|
4228
|
-
|
|
4228
|
+
// Export both ways: default function (for require('./middleware/sentinel'))
|
|
4229
|
+
// and named export (for require('./middleware/sentinel').sentinelMiddleware)
|
|
4230
|
+
module.exports = sentinelMiddleware;
|
|
4231
|
+
module.exports.sentinelMiddleware = sentinelMiddleware;
|
|
4229
4232
|
`;
|
|
4230
4233
|
fs.mkdirSync(path.join(sandboxDir, 'server', 'middleware'), { recursive: true });
|
|
4231
4234
|
fs.writeFileSync(path.join(sandboxDir, 'server', 'middleware', 'sentinel.js'), sentinelShim, 'utf8');
|
|
@@ -4687,7 +4690,9 @@ REGOLE CRITICHE:
|
|
|
4687
4690
|
content = content.replace(toolCall.old, toolCall.new);
|
|
4688
4691
|
fs.writeFileSync(fp, content, 'utf8');
|
|
4689
4692
|
toolResults.push({ op: 'edit', path: toolCall.path, ok: true });
|
|
4690
|
-
sendEv({ type: 'tool', op: 'edit', path: toolCall.path, result: 'ok'
|
|
4693
|
+
sendEv({ type: 'tool', op: 'edit', path: toolCall.path, result: 'ok',
|
|
4694
|
+
oldSnippet: (toolCall.old || '').slice(0, 300),
|
|
4695
|
+
newSnippet: (toolCall.new || '').slice(0, 300) });
|
|
4691
4696
|
} else {
|
|
4692
4697
|
sendEv({ type: 'tool', op: 'edit', path: toolCall.path, result: 'old_string non trovato — patch fallita' });
|
|
4693
4698
|
}
|
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.
|
|
8
|
+
export const VERSION = '13.5.62';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -6975,14 +6975,21 @@ function wcChatPanelHtml() {
|
|
|
6975
6975
|
'</div>';
|
|
6976
6976
|
}
|
|
6977
6977
|
} else if (msg.role === 'system') {
|
|
6978
|
-
// System messages: compact notices (snapshot, syntax check,
|
|
6979
|
-
|
|
6978
|
+
// System messages: compact notices (snapshot, syntax check, error with fix button)
|
|
6979
|
+
var isSandboxErr = (msg.text || '').indexOf('Errore sandbox') !== -1;
|
|
6980
|
+
var borderColor = isSandboxErr ? '#ef4444' : 'var(--border2)';
|
|
6981
|
+
var textColor = isSandboxErr ? '#fca5a5' : 'var(--dim)';
|
|
6982
|
+
messagesHtml += '<div style="margin:4px 12px;padding:6px 10px;background:var(--bg3);border-left:2px solid '+borderColor+';border-radius:4px;font-size:10px;color:'+textColor+';display:flex;align-items:center;gap:8px">' +
|
|
6983
|
+
'<span style="flex:1">' + (msg.text||'') + '</span>' +
|
|
6984
|
+
(isSandboxErr ? '<button onclick="wcFixSandboxError()" style="flex-shrink:0;padding:4px 10px;background:#7f1d1d;border:1px solid #ef4444;border-radius:5px;color:#fca5a5;font-size:10px;font-weight:700;cursor:pointer">🤖 Correggi</button>' : '') +
|
|
6985
|
+
'</div>';
|
|
6980
6986
|
if (msg.syntaxErrors && msg.syntaxErrors.length) {
|
|
6981
6987
|
messagesHtml += '<div style="margin:2px 12px">' + msg.syntaxErrors.map(function(e2){
|
|
6982
6988
|
return '<div style="font-size:10px;font-family:var(--mono);color:#f87171;padding:2px 0">✕ ' + wcEsc(e2.file) + ': ' + wcEsc(e2.error) + '</div>';
|
|
6983
6989
|
}).join('') + '</div>';
|
|
6984
6990
|
}
|
|
6985
6991
|
} else {
|
|
6992
|
+
var diffBlocks = '';
|
|
6986
6993
|
var toolBadges = (msg.tools || []).map(function(tool){
|
|
6987
6994
|
var isOk = tool.result === 'ok';
|
|
6988
6995
|
var isParseErr = tool.op === 'parse_error';
|
|
@@ -6990,6 +6997,17 @@ function wcChatPanelHtml() {
|
|
|
6990
6997
|
var color = isOk ? 'var(--green)' : 'var(--red)';
|
|
6991
6998
|
var label = isParseErr ? ('JSON err: ' + wcEsc(tool.result)) : wcEsc(tool.path);
|
|
6992
6999
|
var title = isOk ? tool.op + ': ' + tool.path : (tool.result || '');
|
|
7000
|
+
// Build inline diff block for successful edits
|
|
7001
|
+
if (isOk && tool.op === 'edit' && tool.oldSnippet) {
|
|
7002
|
+
var oldLines = tool.oldSnippet.split(String.fromCharCode(10)).map(function(l){ return '<div style="background:#3f0f0f;color:#fca5a5;font-family:var(--mono);font-size:9px;padding:0 8px;white-space:pre-wrap;word-break:break-all">- '+wcEsc(l)+'</div>'; }).join('');
|
|
7003
|
+
var newLines = tool.newSnippet.split(String.fromCharCode(10)).map(function(l){ return '<div style="background:#0f2f0f;color:#86efac;font-family:var(--mono);font-size:9px;padding:0 8px;white-space:pre-wrap;word-break:break-all">+ '+wcEsc(l)+'</div>'; }).join('');
|
|
7004
|
+
diffBlocks += '<details style="margin:2px 0;border:1px solid rgba(255,255,255,0.08);border-radius:5px;overflow:hidden">' +
|
|
7005
|
+
'<summary style="padding:3px 8px;font-size:9px;font-family:var(--mono);color:var(--dim);cursor:pointer;list-style:none;display:flex;align-items:center;gap:4px">' +
|
|
7006
|
+
'<span style="color:var(--green)">✎</span> '+wcEsc(tool.path)+' <span style="margin-left:auto;opacity:.5">▼</span>' +
|
|
7007
|
+
'</summary>' +
|
|
7008
|
+
oldLines + newLines +
|
|
7009
|
+
'</details>';
|
|
7010
|
+
}
|
|
6993
7011
|
return '<span title="'+wcEsc(title)+'" style="display:inline-flex;align-items:center;gap:3px;background:var(--bg3);border:1px solid '+(isOk?'var(--green3)':'var(--red)')+';border-radius:4px;padding:2px 6px;font-size:9px;font-family:var(--mono);color:'+color+'">' +
|
|
6994
7012
|
icon + ' ' + label + '</span>';
|
|
6995
7013
|
}).join(' ');
|
|
@@ -7000,6 +7018,7 @@ function wcChatPanelHtml() {
|
|
|
7000
7018
|
'<span style="font-size:10px;font-weight:700;color:var(--green)">WebCraft Agent</span>' +
|
|
7001
7019
|
'</div>' +
|
|
7002
7020
|
'<div style="padding:8px 10px;font-size:11px;color:var(--text);line-height:1.6;white-space:pre-wrap">'+agentText+'</div>' +
|
|
7021
|
+
(diffBlocks ? '<div style="padding:4px 8px 6px;border-top:1px solid rgba(255,255,255,0.06)">'+diffBlocks+'</div>' : '') +
|
|
7003
7022
|
(toolBadges ? '<div style="display:flex;flex-wrap:wrap;gap:4px;padding:6px 10px;border-top:1px solid rgba(255,255,255,0.06)">'+toolBadges+'</div>' : '') +
|
|
7004
7023
|
'</div>';
|
|
7005
7024
|
}
|
|
@@ -7184,7 +7203,7 @@ async function wcExecuteAgentCall(message, isPlanExec, planOrigMsg, attachments)
|
|
|
7184
7203
|
if (typingEl) typingEl.textContent = '...';
|
|
7185
7204
|
wcScrollChatToBottom();
|
|
7186
7205
|
} else if (ev.type === 'tool') {
|
|
7187
|
-
agentMsg.tools.push({ op: ev.op, path: ev.path, result: ev.result });
|
|
7206
|
+
agentMsg.tools.push({ op: ev.op, path: ev.path, result: ev.result, oldSnippet: ev.oldSnippet || '', newSnippet: ev.newSnippet || '' });
|
|
7188
7207
|
if ((ev.op === 'edit' || ev.op === 'write') && ev.result === 'ok') {
|
|
7189
7208
|
anyEdits = true;
|
|
7190
7209
|
wcChat[wcChat.length-1] = agentMsg;
|
|
@@ -7304,7 +7323,7 @@ async function wcTriggerAutoFix(missingModule) {
|
|
|
7304
7323
|
try {
|
|
7305
7324
|
var ev2 = JSON.parse(line2);
|
|
7306
7325
|
if (ev2.type === 'text') { agentMsg.text += ev2.token; }
|
|
7307
|
-
else if (ev2.type === 'tool') { agentMsg.tools.push({ op: ev2.op, path: ev2.path, result: ev2.result }); }
|
|
7326
|
+
else if (ev2.type === 'tool') { agentMsg.tools.push({ op: ev2.op, path: ev2.path, result: ev2.result, oldSnippet: ev2.oldSnippet || '', newSnippet: ev2.newSnippet || '' }); }
|
|
7308
7327
|
else if (ev2.type === 'done') { wcChatRunning = false; if (ev2.changed) { wcReloadProjectFiles(); } }
|
|
7309
7328
|
else if (ev2.type === 'restart_sandbox') { wcStartSandbox(); }
|
|
7310
7329
|
else if (ev2.type === 'error') { agentMsg.text += String.fromCharCode(10)+'Errore: '+ev2.msg; wcChatRunning = false; }
|
|
@@ -7631,7 +7650,7 @@ async function wcGenerate() {
|
|
|
7631
7650
|
|
|
7632
7651
|
// Security rules always injected
|
|
7633
7652
|
var SECURITY_RULES = [
|
|
7634
|
-
'ALWAYS use security headers: X-Content-Type-Options,
|
|
7653
|
+
'ALWAYS use security headers: X-Content-Type-Options, Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy: geolocation=(), microphone=(), camera=(). NEVER set X-Frame-Options: DENY or frame-ancestors: none — the app runs in a sandbox iframe and must be embeddable. HSTS only in production (check NODE_ENV).',
|
|
7635
7654
|
'NEVER put secrets, API keys, or DB credentials in frontend code. Only in .env server-side.',
|
|
7636
7655
|
'ALWAYS use prepared statements / parameterized queries. NEVER string-concatenate SQL.',
|
|
7637
7656
|
'ALWAYS hash passwords with bcrypt (cost factor 12+). NEVER store plain passwords.',
|
|
@@ -7651,7 +7670,7 @@ async function wcGenerate() {
|
|
|
7651
7670
|
{ name: 'package.json', lang: 'json', prompt: 'Generate package.json for an Express/PostgreSQL project named "'+projName+'". Dependencies: express, pg, bcryptjs, jsonwebtoken, nodemailer, helmet, express-rate-limit, cors, dotenv, express-validator, ioredis. DevDependencies: nodemon. Scripts: start, dev.' },
|
|
7652
7671
|
{ name: '.env.example', lang: 'bash', prompt: 'Generate .env.example with all required env vars: DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS, JWT_SECRET, JWT_REFRESH_SECRET, SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM, SENDGRID_API_KEY (commented as optional fallback), REDIS_URL (default redis://localhost:6379, works with Dragonfly too), PORT, NODE_ENV, CORS_ORIGIN, BASE_URL. Add helpful comments for each. Note that REDIS_URL is optional — app falls back to in-memory LRU if Redis unavailable.' },
|
|
7653
7672
|
{ name: 'server/db.js', lang: 'javascript', prompt: 'Generate server/db.js: pg.Pool singleton (max:10, idleTimeoutMillis:30000, connectionTimeoutMillis:2000). Circuit breaker: if DB fails 5+ times in 60s, open circuit (throw immediately) for 30s, then half-open (try one query). Export pool, query(text, params) with circuit breaker, transaction(callback) helper (BEGIN/COMMIT/ROLLBACK). Graceful shutdown on SIGTERM/SIGINT.' },
|
|
7654
|
-
{ name: 'server/middleware/security.js', lang: 'javascript', prompt: 'Generate server/middleware/security.js:
|
|
7673
|
+
{ name: 'server/middleware/security.js', lang: 'javascript', prompt: 'Generate server/middleware/security.js: detect sandbox via isSandbox = !process.env.NODE_ENV || process.env.NODE_ENV === "development". Use helmet CSP: defaultSrc self, scriptSrc self unsafe-inline, styleSrc self unsafe-inline, imgSrc self data:, connectSrc self, objectSrc none. frameAncestors: if isSandbox use ["self", "http://127.0.0.1:*", "http://localhost:*"] else ["none"]. NO X-Frame-Options DENY (conflicts with frameAncestors). NO HSTS in sandbox (HTTP only). Referrer-Policy strict-origin-when-cross-origin. Add express-rate-limit for general routes (100/15min) and strict limiter for auth (5/15min). Export { applySecurityMiddleware, authLimiter }.' },
|
|
7655
7674
|
{ name: 'server/middleware/validate.js', lang: 'javascript', prompt: 'Generate server/middleware/validate.js using express-validator. Export handleValidationErrors middleware. Export auth field validators: registerValidator (fields: '+authFieldsDef+'), loginValidator (email + password).' },
|
|
7656
7675
|
{ name: 'server/services/email.js', lang: 'javascript', prompt: 'Generate server/services/email.js: Nodemailer transporter using SMTP from env. Function sendVerificationEmail(to, token, baseUrl): sends HTML email with verification link. Function sendPasswordResetEmail(to, token, baseUrl). Add SendGrid fallback (commented out, predisposed with transporter swap). Never expose credentials.' },
|
|
7657
7676
|
{ name: 'server/routes/auth.js', lang: 'javascript', prompt: 'Generate server/routes/auth.js: POST /register (validate fields: '+authFieldsDef+', check duplicate email, bcrypt hash password cost 12, insert user, send verification email, return 201), POST /login (validate, check email verified, compare bcrypt, issue JWT access 15min + refresh 7d httpOnly cookie), POST /logout (clear refresh cookie), POST /refresh-token (validate refresh from httpOnly cookie, rotate token), GET /verify-email/:token (mark email verified). Use parameterized queries only. Apply authLimiter to register and login.' },
|
|
@@ -7857,7 +7876,12 @@ function wcSandboxPanelHtml() {
|
|
|
7857
7876
|
|
|
7858
7877
|
return '<div style="display:flex;flex-direction:column;flex:1;min-height:0;overflow-y:auto">' +
|
|
7859
7878
|
phasesHtml +
|
|
7860
|
-
(sb.error ?
|
|
7879
|
+
(sb.error ?
|
|
7880
|
+
'<div style="padding:10px 14px;border-top:1px solid var(--border);display:flex;align-items:flex-start;gap:10px;flex-wrap:wrap">' +
|
|
7881
|
+
'<div style="flex:1;min-width:0;font-size:11px;font-family:var(--mono);color:var(--red);white-space:pre-wrap;word-break:break-all">❌ '+wcEsc(sb.error)+'</div>' +
|
|
7882
|
+
'<button onclick="wcFixSandboxError()" style="flex-shrink:0;padding:6px 14px;background:#7f1d1d;border:1px solid #ef4444;border-radius:6px;color:#fca5a5;font-size:11px;font-weight:700;cursor:pointer;white-space:nowrap">🤖 Correggi</button>' +
|
|
7883
|
+
'</div>'
|
|
7884
|
+
: '') +
|
|
7861
7885
|
'</div>';
|
|
7862
7886
|
}
|
|
7863
7887
|
|
|
@@ -7948,6 +7972,66 @@ async function wcStopSandbox() {
|
|
|
7948
7972
|
renderWebCraft(document.getElementById('content'));
|
|
7949
7973
|
}
|
|
7950
7974
|
|
|
7975
|
+
// "Correggi" button — sends full sandbox error to the agent for repair
|
|
7976
|
+
async function wcFixSandboxError() {
|
|
7977
|
+
var errText = wcState.sandbox.error || 'Errore sconosciuto avviando il server sandbox';
|
|
7978
|
+
// Put error in chat input so user can see it, then fire agent
|
|
7979
|
+
var fixMsg = 'ERRORE SANDBOX — il server Node.js non si avvia. Analizza tutti i file del progetto, trova la causa e correggi.' +
|
|
7980
|
+
String.fromCharCode(10) + String.fromCharCode(10) +
|
|
7981
|
+
'STACKTRACE COMPLETO:' + String.fromCharCode(10) + errText;
|
|
7982
|
+
// Push as user message so it appears in chat
|
|
7983
|
+
wcChat.push({ role: 'user', text: '🤖 Correggi errore sandbox' });
|
|
7984
|
+
wcScrollChatToBottom();
|
|
7985
|
+
wcChatRunning = true;
|
|
7986
|
+
renderWebCraft(document.getElementById('content'));
|
|
7987
|
+
|
|
7988
|
+
try {
|
|
7989
|
+
var r = await fetch(API + '/api/studio/webcraft/agent', {
|
|
7990
|
+
method: 'POST',
|
|
7991
|
+
headers: { 'Content-Type': 'application/json' },
|
|
7992
|
+
body: JSON.stringify({ projectName: wcState.projectName, message: fixMsg, autofix: true })
|
|
7993
|
+
});
|
|
7994
|
+
if (!r.ok) { wcChatRunning = false; renderWebCraft(document.getElementById('content')); return; }
|
|
7995
|
+
var agentMsg = { role: 'agent', text: '', tools: [] };
|
|
7996
|
+
wcChat.push(agentMsg);
|
|
7997
|
+
var reader4 = r.body.getReader();
|
|
7998
|
+
var dec4 = new TextDecoder();
|
|
7999
|
+
var buf4 = '';
|
|
8000
|
+
while (true) {
|
|
8001
|
+
var res4 = await reader4.read();
|
|
8002
|
+
if (res4.done) break;
|
|
8003
|
+
buf4 += dec4.decode(res4.value, { stream: true });
|
|
8004
|
+
var parts4 = buf4.split(String.fromCharCode(10) + String.fromCharCode(10));
|
|
8005
|
+
buf4 = parts4.pop();
|
|
8006
|
+
for (var pi4 = 0; pi4 < parts4.length; pi4++) {
|
|
8007
|
+
var line4 = parts4[pi4].replace(/^data: /, '').trim();
|
|
8008
|
+
if (!line4) continue;
|
|
8009
|
+
try {
|
|
8010
|
+
var ev4 = JSON.parse(line4);
|
|
8011
|
+
if (ev4.type === 'text') { agentMsg.text += ev4.token; renderWebCraft(document.getElementById('content')); wcScrollChatToBottom(); }
|
|
8012
|
+
else if (ev4.type === 'tool') { agentMsg.tools.push({ op: ev4.op, path: ev4.path, result: ev4.result }); renderWebCraft(document.getElementById('content')); }
|
|
8013
|
+
else if (ev4.type === 'done') {
|
|
8014
|
+
wcChatRunning = false;
|
|
8015
|
+
if (ev4.changed) {
|
|
8016
|
+
// Files changed — syntax check then offer to restart
|
|
8017
|
+
wcChat.push({ role: 'system', text: '✅ Fix applicato. Clicca ▶ Avvia Sandbox per ritentare.' });
|
|
8018
|
+
}
|
|
8019
|
+
renderWebCraft(document.getElementById('content'));
|
|
8020
|
+
wcScrollChatToBottom();
|
|
8021
|
+
} else if (ev4.type === 'restart_sandbox') {
|
|
8022
|
+
wcState.sandbox = { running: false, port: null, dir: null, logs: [], error: null };
|
|
8023
|
+
setTimeout(function(){ wcStartSandbox(); }, 800);
|
|
8024
|
+
}
|
|
8025
|
+
} catch(_) {}
|
|
8026
|
+
}
|
|
8027
|
+
}
|
|
8028
|
+
} catch(e2) {
|
|
8029
|
+
wcChatRunning = false;
|
|
8030
|
+
wcChat.push({ role: 'system', text: '❌ Errore chiamata agente: ' + e2.message });
|
|
8031
|
+
renderWebCraft(document.getElementById('content'));
|
|
8032
|
+
}
|
|
8033
|
+
}
|
|
8034
|
+
|
|
7951
8035
|
var _wcLastDownload = 0;
|
|
7952
8036
|
function wcDownloadZip() {
|
|
7953
8037
|
if (!wcState.generatedFiles.length) return;
|