nothumanallowed 13.5.80 → 13.5.82
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/services/web-ui.mjs +144 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.82",
|
|
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/services/web-ui.mjs
CHANGED
|
@@ -6568,7 +6568,7 @@ function renderWebCraft(el) {
|
|
|
6568
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
|
-
var hasErr = !!f._error;
|
|
6571
|
+
var hasErr = !!f._error || !!f._syntaxError;
|
|
6572
6572
|
var tabColor = hasErr ? (active ? '#f87171' : '#7f4040') : (active ? 'var(--green)' : 'var(--dim)');
|
|
6573
6573
|
var tabBorder = hasErr ? (active ? '#f87171' : 'transparent') : (active ? 'var(--green3)' : 'transparent');
|
|
6574
6574
|
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 '+tabBorder+';color:'+tabColor+';cursor:pointer;white-space:nowrap;flex-shrink:0">'+(hasErr?'⚠ ':'')+wcEsc(f.name)+'</button>';
|
|
@@ -6579,8 +6579,8 @@ function renderWebCraft(el) {
|
|
|
6579
6579
|
var _activeFile = wcState.generatedFiles[wcState.activeFile];
|
|
6580
6580
|
var codeHtml = wcState.generatedFiles.length > 0 && _activeFile
|
|
6581
6581
|
? '<div id="wcCodeWrap" style="flex:1;overflow:auto;background:var(--bg3);border-radius:0 0 8px 8px">' +
|
|
6582
|
-
(_activeFile._error ? '<div style="padding:8px 14px;background:rgba(239,68,68,0.12);border-bottom:1px solid rgba(239,68,68,0.3);font-size:11px;color:#f87171;display:flex;align-items:center;gap:6px">⚠ Generazione fallita — chiedi al modello di rigenerare questo file</div>' : '') +
|
|
6583
|
-
'<pre style="margin:0;padding:14px 16px;font-size:11px;line-height:1.6;color:'+(_activeFile._error?'#f87171':'var(--text)')+';font-family:var(--mono);white-space:pre-wrap;word-break:break-all">'+wcEsc(_activeFile.content)+'</pre>' +
|
|
6582
|
+
(_activeFile._error ? '<div style="padding:8px 14px;background:rgba(239,68,68,0.12);border-bottom:1px solid rgba(239,68,68,0.3);font-size:11px;color:#f87171;display:flex;align-items:center;gap:6px">⚠ Generazione fallita — chiedi al modello di rigenerare questo file</div>' : (_activeFile._syntaxError ? '<div style="padding:8px 14px;background:rgba(234,179,8,0.1);border-bottom:1px solid rgba(234,179,8,0.3);font-size:11px;color:#facc15;display:flex;align-items:center;gap:6px">⚠ Syntax error: '+wcEsc(_activeFile._syntaxError)+'</div>' : '')) +
|
|
6583
|
+
'<pre style="margin:0;padding:14px 16px;font-size:11px;line-height:1.6;color:'+(_activeFile._error?'#f87171':_activeFile._syntaxError?'#fde68a':'var(--text)')+';font-family:var(--mono);white-space:pre-wrap;word-break:break-all">'+wcEsc(_activeFile.content)+'</pre>' +
|
|
6584
6584
|
'</div>'
|
|
6585
6585
|
: '<div style="flex:1;display:flex;align-items:center;justify-content:center;color:var(--dim);font-size:12px;flex-direction:column;gap:8px">' +
|
|
6586
6586
|
'<span style="font-size:36px;opacity:.25">🛠</span>' +
|
|
@@ -7890,7 +7890,7 @@ async function wcGenerate() {
|
|
|
7890
7890
|
// Helper: generate one file, returns {ok, content} or {ok:false, err}
|
|
7891
7891
|
async function wcGenOneFile(fp, signal) {
|
|
7892
7892
|
var _nl2 = String.fromCharCode(10);
|
|
7893
|
-
var content = await wcCallLLM(sysPreamble, fp.prompt + _nl2 + _nl2 + 'File to generate: ' + fp.name, signal);
|
|
7893
|
+
var content = await wcCallLLM(sysPreamble, fp.prompt + _nl2 + _nl2 + 'File to generate: ' + fp.name, signal, fp.lang);
|
|
7894
7894
|
var _fence = String.fromCharCode(96,96,96);
|
|
7895
7895
|
var wcLines = content.split(_nl2);
|
|
7896
7896
|
if (wcLines.length > 0 && wcLines[0].indexOf(_fence) === 0) wcLines.shift();
|
|
@@ -7942,6 +7942,62 @@ async function wcGenerate() {
|
|
|
7942
7942
|
}
|
|
7943
7943
|
}
|
|
7944
7944
|
|
|
7945
|
+
// ── Post-generation syntax scan ──────────────────────────────────────────
|
|
7946
|
+
// Zero LLM calls — pure structural check on every generated file
|
|
7947
|
+
// Files with syntax errors get _syntaxError set and are re-queued for retry
|
|
7948
|
+
var syntaxFailedNames = [];
|
|
7949
|
+
wcState.generatedFiles.forEach(function(f) {
|
|
7950
|
+
if (f._error) return; // already failed at LLM level
|
|
7951
|
+
var lang = f.lang || (f.name.endsWith('.css') ? 'css' : f.name.endsWith('.js') ? 'javascript' : f.name.endsWith('.html') ? 'html' : f.name.endsWith('.json') ? 'json' : 'text');
|
|
7952
|
+
var check = wcSyntaxCheck(f.content, lang);
|
|
7953
|
+
if (!check.ok) {
|
|
7954
|
+
f._syntaxError = check.reason;
|
|
7955
|
+
syntaxFailedNames.push(f.name);
|
|
7956
|
+
} else {
|
|
7957
|
+
delete f._syntaxError;
|
|
7958
|
+
}
|
|
7959
|
+
});
|
|
7960
|
+
|
|
7961
|
+
// Re-fix syntax-broken files — continue/patch, do NOT regenerate from scratch
|
|
7962
|
+
if (syntaxFailedNames.length > 0 && !(_wcGenAbortCtrl && _wcGenAbortCtrl.signal.aborted)) {
|
|
7963
|
+
var syntaxRetryPlan = filePlan.filter(function(fp2){ return syntaxFailedNames.indexOf(fp2.name) !== -1; });
|
|
7964
|
+
for (var si2 = 0; si2 < syntaxRetryPlan.length; si2++) {
|
|
7965
|
+
var sfp = syntaxRetryPlan[si2];
|
|
7966
|
+
var brokenFile = wcState.generatedFiles.filter(function(f){ return f.name === sfp.name; })[0];
|
|
7967
|
+
if (!brokenFile) continue;
|
|
7968
|
+
wcUpdateGenOverlay(si2, syntaxRetryPlan.length, 'Fix: ' + sfp.name);
|
|
7969
|
+
if (_wcGenAbortCtrl && _wcGenAbortCtrl.signal.aborted) break;
|
|
7970
|
+
await new Promise(function(resolve){ setTimeout(resolve, 1500); });
|
|
7971
|
+
try {
|
|
7972
|
+
var _nl3 = String.fromCharCode(10);
|
|
7973
|
+
// Build a targeted fix prompt — pass the broken file and ask only for the fix/completion
|
|
7974
|
+
var fixSys = sysPreamble + _nl3 + 'You are fixing a truncated or broken file. Output ONLY the corrected complete file content. No explanations, no markdown fences.';
|
|
7975
|
+
var fixUser = 'File: ' + sfp.name + _nl3 +
|
|
7976
|
+
'Syntax error: ' + (brokenFile._syntaxError || 'truncated') + _nl3 + _nl3 +
|
|
7977
|
+
'Current (broken) content:' + _nl3 + brokenFile.content + _nl3 + _nl3 +
|
|
7978
|
+
'Output the complete corrected file. If it was truncated, continue from where it stopped and output the FULL file from the beginning.';
|
|
7979
|
+
var fixedContent = await wcCallLLM(fixSys, fixUser, _wcGenAbortCtrl ? _wcGenAbortCtrl.signal : null, sfp.lang);
|
|
7980
|
+
// Strip fences if model added them
|
|
7981
|
+
var _fence2 = String.fromCharCode(96,96,96);
|
|
7982
|
+
var fixLines = fixedContent.split(_nl3);
|
|
7983
|
+
if (fixLines.length > 0 && fixLines[0].indexOf(_fence2) === 0) fixLines.shift();
|
|
7984
|
+
if (fixLines.length > 0 && fixLines[fixLines.length-1].trim() === _fence2) fixLines.pop();
|
|
7985
|
+
fixedContent = fixLines.join(_nl3).trim();
|
|
7986
|
+
var fixCheck = wcSyntaxCheck(fixedContent, sfp.lang);
|
|
7987
|
+
for (var gi2 = 0; gi2 < wcState.generatedFiles.length; gi2++) {
|
|
7988
|
+
if (wcState.generatedFiles[gi2].name === sfp.name) {
|
|
7989
|
+
wcState.generatedFiles[gi2] = { name: sfp.name, content: fixedContent, lang: sfp.lang };
|
|
7990
|
+
if (!fixCheck.ok) wcState.generatedFiles[gi2]._syntaxError = fixCheck.reason;
|
|
7991
|
+
break;
|
|
7992
|
+
}
|
|
7993
|
+
}
|
|
7994
|
+
renderWebCraft(document.getElementById('content'));
|
|
7995
|
+
} catch(se) {
|
|
7996
|
+
if (se && se.name === 'AbortError') break;
|
|
7997
|
+
}
|
|
7998
|
+
}
|
|
7999
|
+
}
|
|
8000
|
+
|
|
7945
8001
|
wcState.running = false;
|
|
7946
8002
|
_wcGenAbortCtrl = null;
|
|
7947
8003
|
_wcOverlayMinimized = false;
|
|
@@ -7958,14 +8014,79 @@ async function wcGenerate() {
|
|
|
7958
8014
|
renderWebCraft(document.getElementById('content'));
|
|
7959
8015
|
}
|
|
7960
8016
|
|
|
7961
|
-
|
|
8017
|
+
// Quick structural check — returns {ok, reason} without calling the LLM
|
|
8018
|
+
// Reads only structure (braces, tags) — does NOT add content to any context
|
|
8019
|
+
function wcSyntaxCheck(content, lang) {
|
|
8020
|
+
if (!content || content.length < 20) return { ok: false, reason: 'empty' };
|
|
8021
|
+
var trimmed = content.trimEnd();
|
|
8022
|
+
|
|
8023
|
+
if (lang === 'css' || lang === 'scss') {
|
|
8024
|
+
// Strip comments and strings to avoid false brace counts
|
|
8025
|
+
var stripped = trimmed
|
|
8026
|
+
.replace(new RegExp('/[*][\\s\\S]*?[*]/', 'g'), '')
|
|
8027
|
+
.replace(new RegExp('"[^"]*"', 'g'), '""')
|
|
8028
|
+
.replace(new RegExp("['][^']*[']", 'g'), "''");
|
|
8029
|
+
var open = 0, close = 0;
|
|
8030
|
+
for (var i = 0; i < stripped.length; i++) {
|
|
8031
|
+
if (stripped[i] === '{') open++;
|
|
8032
|
+
else if (stripped[i] === '}') close++;
|
|
8033
|
+
}
|
|
8034
|
+
if (open !== close) return { ok: false, reason: 'unbalanced braces (' + open + ' open, ' + close + ' close)' };
|
|
8035
|
+
if (open === 0) return { ok: false, reason: 'no CSS rules found' };
|
|
8036
|
+
return { ok: true };
|
|
8037
|
+
}
|
|
8038
|
+
|
|
8039
|
+
if (lang === 'javascript') {
|
|
8040
|
+
// Use Function constructor as a zero-overhead parse check (no eval, just syntax)
|
|
8041
|
+
try { new Function(content); return { ok: true }; }
|
|
8042
|
+
catch(e) { return { ok: false, reason: e.message.split(String.fromCharCode(10))[0] }; }
|
|
8043
|
+
}
|
|
8044
|
+
|
|
8045
|
+
if (lang === 'html') {
|
|
8046
|
+
var lower = trimmed.toLowerCase();
|
|
8047
|
+
if (lower.indexOf('</html>') === -1 && lower.indexOf('</body>') === -1)
|
|
8048
|
+
return { ok: false, reason: 'missing </html> or </body>' };
|
|
8049
|
+
// DOMParser check for well-formedness
|
|
8050
|
+
try {
|
|
8051
|
+
var doc = new DOMParser().parseFromString(trimmed, 'text/html');
|
|
8052
|
+
var pe = doc.querySelector('parseerror');
|
|
8053
|
+
if (pe) return { ok: false, reason: pe.textContent.slice(0, 80) };
|
|
8054
|
+
} catch(_) {}
|
|
8055
|
+
return { ok: true };
|
|
8056
|
+
}
|
|
8057
|
+
|
|
8058
|
+
if (lang === 'json') {
|
|
8059
|
+
try { JSON.parse(trimmed); return { ok: true }; }
|
|
8060
|
+
catch(e) { return { ok: false, reason: e.message }; }
|
|
8061
|
+
}
|
|
8062
|
+
|
|
8063
|
+
// For markdown, nginx.conf, sql, bash — just check not truncated mid-line
|
|
8064
|
+
var last = trimmed[trimmed.length - 1];
|
|
8065
|
+
if (last === undefined) return { ok: false, reason: 'empty' };
|
|
8066
|
+
return { ok: true };
|
|
8067
|
+
}
|
|
8068
|
+
|
|
8069
|
+
// Returns true if content looks truncated (unbalanced braces or ends mid-rule)
|
|
8070
|
+
function wcIsTruncated(content, lang) {
|
|
8071
|
+
if (!content || content.length < 100) return false;
|
|
8072
|
+
var check = wcSyntaxCheck(content, lang);
|
|
8073
|
+
if (!check.ok) return true;
|
|
8074
|
+
// Also check raw ending for langs not fully covered above
|
|
8075
|
+
var trimmed = content.trimEnd();
|
|
8076
|
+
if (lang === 'javascript') {
|
|
8077
|
+
var last = trimmed[trimmed.length - 1];
|
|
8078
|
+
return last !== '}' && last !== ';' && last !== ')';
|
|
8079
|
+
}
|
|
8080
|
+
return false;
|
|
8081
|
+
}
|
|
8082
|
+
|
|
8083
|
+
async function wcCallLLMRaw(sys, user, signal) {
|
|
7962
8084
|
var fetchOpts = {
|
|
7963
8085
|
method: 'POST',
|
|
7964
8086
|
headers: {'Content-Type':'application/json'},
|
|
7965
8087
|
body: JSON.stringify({system: sys, user: user, max_tokens: 4096})
|
|
7966
8088
|
};
|
|
7967
8089
|
if (signal) fetchOpts.signal = signal;
|
|
7968
|
-
// Retry up to 2 times on 5xx errors (Liara may be temporarily overloaded)
|
|
7969
8090
|
for (var attempt = 0; attempt < 3; attempt++) {
|
|
7970
8091
|
if (signal && signal.aborted) throw new DOMException('Aborted', 'AbortError');
|
|
7971
8092
|
var r = await fetch(API + '/api/studio/webcraft', fetchOpts);
|
|
@@ -7978,11 +8099,27 @@ async function wcCallLLM(sys, user, signal) {
|
|
|
7978
8099
|
try { var eb = await r.json(); errBody = eb.error || ''; } catch(_) {}
|
|
7979
8100
|
throw new Error('LLM error ' + r.status + (errBody ? ': ' + errBody : ''));
|
|
7980
8101
|
}
|
|
7981
|
-
// 5xx — wait 2s then retry
|
|
7982
8102
|
await new Promise(function(resolve) { setTimeout(resolve, 2000); });
|
|
7983
8103
|
}
|
|
7984
8104
|
}
|
|
7985
8105
|
|
|
8106
|
+
async function wcCallLLM(sys, user, signal, lang) {
|
|
8107
|
+
var content = await wcCallLLMRaw(sys, user, signal);
|
|
8108
|
+
// Continuation loop: if response is truncated, ask model to continue
|
|
8109
|
+
var maxContinuations = 2;
|
|
8110
|
+
for (var ci = 0; ci < maxContinuations; ci++) {
|
|
8111
|
+
if (!wcIsTruncated(content, lang || 'text')) break;
|
|
8112
|
+
if (signal && signal.aborted) break;
|
|
8113
|
+
var continuePrompt = 'Continue generating the file EXACTLY from where you stopped. Do not repeat anything already written. Output ONLY the remaining code, starting from the next character after where you stopped.' +
|
|
8114
|
+
String.fromCharCode(10) + String.fromCharCode(10) + 'The file so far ends with:' +
|
|
8115
|
+
String.fromCharCode(10) + content.slice(-300);
|
|
8116
|
+
var continuation = await wcCallLLMRaw(sys, continuePrompt, signal);
|
|
8117
|
+
if (!continuation || continuation.trim().length < 5) break;
|
|
8118
|
+
content = content + String.fromCharCode(10) + continuation;
|
|
8119
|
+
}
|
|
8120
|
+
return content;
|
|
8121
|
+
}
|
|
8122
|
+
|
|
7986
8123
|
function wcSandboxPanelHtml() {
|
|
7987
8124
|
var sb = wcState.sandbox;
|
|
7988
8125
|
if (!wcState.generatedFiles.length) {
|