nothumanallowed 13.5.87 → 13.5.88

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.87",
3
+ "version": "13.5.88",
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": {
@@ -6528,7 +6528,11 @@ var wcState = {
6528
6528
  logs: [],
6529
6529
  error: null
6530
6530
  },
6531
- lastGenStats: null
6531
+ lastGenStats: null,
6532
+ repairing: false,
6533
+ repairTotal: 0,
6534
+ repairDone: 0,
6535
+ repairCurrent: ''
6532
6536
  };
6533
6537
  var wcRightTab = 'files';
6534
6538
  var wcMainTab = 'new'; // 'new' | 'projects'
@@ -6550,6 +6554,8 @@ var _wcOverlayTimer = null; // inactivity timer to restore overlay
6550
6554
  var _wcGenAbortCtrl = null; // AbortController for generation stop
6551
6555
  var _wcSyntaxResults = []; // [{file, ok, error}]
6552
6556
  var _wcSnapshots = []; // [{ts, fileCount}]
6557
+ var _wcLastFilePlan = []; // saved for manual repair trigger
6558
+ var _wcLastSysPreamble = '';
6553
6559
  // Skills state
6554
6560
  var wcSkills = []; // [{name, content, type}] type: 'skill'|'memory'|'provider'
6555
6561
  var wcSkillModal = null; // null | {mode:'edit'|'new', idx:number|null, name, content, type, generating}
@@ -6694,6 +6700,13 @@ function renderWebCraft(el) {
6694
6700
  (wcState.running ?
6695
6701
  '<div style="width:100%;padding:11px;background:var(--bg3);border:1px solid var(--border);border-radius:8px;color:var(--dim);font-size:12px;text-align:center">&#9203; '+t('wc_generating')+'...</div>'
6696
6702
  : '') +
6703
+ (wcState.repairing ?
6704
+ '<div style="width:100%;padding:10px 12px;background:rgba(234,179,8,0.08);border:1px solid rgba(234,179,8,0.4);border-radius:8px;display:flex;flex-direction:column;gap:4px">' +
6705
+ '<div style="display:flex;align-items:center;gap:6px;font-size:11px;color:#facc15;font-weight:600">&#128295; Correzione automatica in corso...</div>' +
6706
+ '<div style="font-size:10px;color:var(--dim)">'+wcState.repairDone+' / '+wcState.repairTotal+' file</div>' +
6707
+ (wcState.repairCurrent ? '<div style="font-size:10px;color:#fde68a;font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+wcEsc(wcState.repairCurrent)+'</div>' : '') +
6708
+ '</div>'
6709
+ : '') +
6697
6710
  (wcState.generatedFiles.length > 0 && !wcState.running ?
6698
6711
  '<div style="display:flex;gap:6px;flex-wrap:wrap">' +
6699
6712
  '<button onclick="wcDownloadZip()" style="flex:1;padding:9px;background:var(--bg3);border:1px solid var(--border2);border-radius:8px;color:var(--text);font-size:11px;font-weight:600;cursor:pointer">&#8681; ZIP</button>' +
@@ -6701,6 +6714,9 @@ function renderWebCraft(el) {
6701
6714
  '<button onclick="wcToggleGrep()" title="Cerca nel codice" style="padding:9px 10px;background:'+(_wcGrepOpen?'var(--greendim)':'var(--bg3)')+';border:1px solid '+(_wcGrepOpen?'var(--green3)':'var(--border2)')+';border-radius:8px;color:'+(_wcGrepOpen?'var(--green)':'var(--dim)')+';font-size:11px;cursor:pointer">&#128269;</button>' +
6702
6715
  '<button onclick="wcManualSnapshot()" title="Salva snapshot" style="padding:9px 10px;background:var(--bg3);border:1px solid var(--border2);border-radius:8px;color:var(--dim);font-size:11px;cursor:pointer">&#128190;</button>' +
6703
6716
  '</div>' +
6717
+ (wcState.generatedFiles.some(function(f){ return f._error || f._syntaxError; }) && !wcState.repairing ?
6718
+ '<button onclick="wcTriggerRepair()" style="width:100%;padding:9px;background:rgba(234,179,8,0.08);border:1px solid rgba(234,179,8,0.5);border-radius:8px;color:#facc15;font-size:11px;font-weight:600;cursor:pointer">&#128295; Correggi tutti i file rossi</button>'
6719
+ : '') +
6704
6720
  '<button onclick="wcStartSandbox()" id="wcSandboxBtn" style="width:100%;padding:10px;background:var(--bg3);border:1px solid var(--green3);border-radius:8px;color:var(--green);font-size:12px;font-weight:600;cursor:pointer">&#9654; '+t('wc_sandbox_start')+'</button>' +
6705
6721
  (wcState.lastGenStats ? '<div style="padding:6px 8px;background:var(--bg3);border:1px solid var(--border);border-radius:6px;font-size:10px;color:var(--dim);font-family:var(--mono);display:flex;flex-wrap:wrap;gap:6px">' +
6706
6722
  '<span>&#9201; '+(wcState.lastGenStats.seconds >= 60 ? Math.floor(wcState.lastGenStats.seconds/60)+'m '+(wcState.lastGenStats.seconds%60)+'s' : wcState.lastGenStats.seconds+'s')+'</span>' +
@@ -7916,6 +7932,8 @@ async function wcGenerate() {
7916
7932
 
7917
7933
  var _nl = String.fromCharCode(10);
7918
7934
  var sysPreamble = 'You are an expert full-stack engineer generating production-quality code.' + _nl + _nl + 'SECURITY RULES (non-negotiable):' + _nl + SECURITY_RULES + _nl + _nl + 'Project: ' + projName + _nl + 'Description: ' + desc + _nl + 'Enabled blocks: ' + blocksEnabled + _nl + _nl + 'Generate ONLY the file content requested. No explanations, no markdown code fences, no comments like "here is the file". Output raw file content only.';
7935
+ _wcLastFilePlan = filePlan;
7936
+ _wcLastSysPreamble = sysPreamble;
7919
7937
 
7920
7938
  var _wcGenStartTime = Date.now();
7921
7939
  var _wcTokIn = 0, _wcTokOut = 0;
@@ -8023,103 +8041,105 @@ async function wcGenerate() {
8023
8041
  renderWebCraft(document.getElementById('content'));
8024
8042
  }
8025
8043
 
8026
- // ── Retry pass: regenerate files that failed ──────────────────────────────
8027
- var failedFiles = wcState.generatedFiles.filter(function(f){ return f._error; });
8028
- if (failedFiles.length > 0 && !(_wcGenAbortCtrl && _wcGenAbortCtrl.signal.aborted)) {
8029
- var retryPlan = filePlan.filter(function(fp){ return failedFiles.some(function(f){ return f.name === fp.name; }); });
8030
- for (var ri = 0; ri < retryPlan.length; ri++) {
8031
- var rfp = retryPlan[ri];
8032
- wcUpdateGenOverlay(ri, retryPlan.length, 'Retry: ' + rfp.name);
8033
- if (_wcGenAbortCtrl && _wcGenAbortCtrl.signal.aborted) break;
8034
- // Wait 3s before retry to let Liara recover
8035
- await new Promise(function(resolve){ setTimeout(resolve, 3000); });
8036
- try {
8037
- var retryContent = await wcGenOneFile(rfp, _wcGenAbortCtrl ? _wcGenAbortCtrl.signal : null);
8038
- // Replace the error entry with the successful one
8039
- for (var gi = 0; gi < wcState.generatedFiles.length; gi++) {
8040
- if (wcState.generatedFiles[gi].name === rfp.name) {
8041
- wcState.generatedFiles[gi] = { name: rfp.name, content: retryContent, lang: rfp.lang };
8042
- break;
8043
- }
8044
- }
8045
- renderWebCraft(document.getElementById('content'));
8046
- } catch(re) {
8047
- if (re && re.name === 'AbortError') break;
8048
- // Keep as error — already in generatedFiles
8049
- }
8050
- }
8051
- }
8052
-
8053
- // ── Post-generation syntax scan ──────────────────────────────────────────
8054
- // Zero LLM calls — pure structural check on every generated file
8055
- // Files with syntax errors get _syntaxError set and are re-queued for retry
8056
- var syntaxFailedNames = [];
8057
- wcState.generatedFiles.forEach(function(f) {
8058
- if (f._error) return; // already failed at LLM level
8059
- 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');
8060
- var check = wcSyntaxCheck(f.content, lang);
8061
- if (!check.ok) {
8062
- f._syntaxError = check.reason;
8063
- syntaxFailedNames.push(f.name);
8064
- } else {
8065
- delete f._syntaxError;
8066
- }
8067
- });
8068
-
8069
- // Re-fix syntax-broken files — continue/patch, do NOT regenerate from scratch
8070
- if (syntaxFailedNames.length > 0 && !(_wcGenAbortCtrl && _wcGenAbortCtrl.signal.aborted)) {
8071
- var syntaxRetryPlan = filePlan.filter(function(fp2){ return syntaxFailedNames.indexOf(fp2.name) !== -1; });
8072
- for (var si2 = 0; si2 < syntaxRetryPlan.length; si2++) {
8073
- var sfp = syntaxRetryPlan[si2];
8074
- var brokenFile = wcState.generatedFiles.filter(function(f){ return f.name === sfp.name; })[0];
8075
- if (!brokenFile) continue;
8076
- wcUpdateGenOverlay(si2, syntaxRetryPlan.length, 'Fix: ' + sfp.name);
8077
- if (_wcGenAbortCtrl && _wcGenAbortCtrl.signal.aborted) break;
8078
- await new Promise(function(resolve){ setTimeout(resolve, 1500); });
8079
- try {
8080
- var _nl3 = String.fromCharCode(10);
8081
- // Build a targeted fix prompt — pass the broken file and ask only for the fix/completion
8082
- var fixSys = sysPreamble + _nl3 + 'You are fixing a truncated or broken file. Output ONLY the corrected complete file content. No explanations, no markdown fences.';
8083
- var fixUser = 'File: ' + sfp.name + _nl3 +
8084
- 'Syntax error: ' + (brokenFile._syntaxError || 'truncated') + _nl3 + _nl3 +
8085
- 'Current (broken) content:' + _nl3 + brokenFile.content + _nl3 + _nl3 +
8086
- 'Output the complete corrected file. If it was truncated, continue from where it stopped and output the FULL file from the beginning.';
8087
- var fixedContent = await wcCallLLM(fixSys, fixUser, _wcGenAbortCtrl ? _wcGenAbortCtrl.signal : null, sfp.lang);
8088
- // Strip fences if model added them
8089
- var _fence2 = String.fromCharCode(96,96,96);
8090
- var fixLines = fixedContent.split(_nl3);
8091
- if (fixLines.length > 0 && fixLines[0].indexOf(_fence2) === 0) fixLines.shift();
8092
- if (fixLines.length > 0 && fixLines[fixLines.length-1].trim() === _fence2) fixLines.pop();
8093
- fixedContent = fixLines.join(_nl3).trim();
8094
- var fixCheck = wcSyntaxCheck(fixedContent, sfp.lang);
8095
- for (var gi2 = 0; gi2 < wcState.generatedFiles.length; gi2++) {
8096
- if (wcState.generatedFiles[gi2].name === sfp.name) {
8097
- wcState.generatedFiles[gi2] = { name: sfp.name, content: fixedContent, lang: sfp.lang };
8098
- if (!fixCheck.ok) wcState.generatedFiles[gi2]._syntaxError = fixCheck.reason;
8099
- break;
8100
- }
8101
- }
8102
- renderWebCraft(document.getElementById('content'));
8103
- } catch(se) {
8104
- if (se && se.name === 'AbortError') break;
8105
- }
8106
- }
8107
- }
8108
-
8109
8044
  if (_wcTimerInterval) { clearInterval(_wcTimerInterval); _wcTimerInterval = null; }
8110
8045
  var _wcGenTotalTime = Math.floor((Date.now() - _wcGenStartTime) / 1000);
8111
8046
 
8112
8047
  wcState.running = false;
8113
8048
  _wcGenAbortCtrl = null;
8114
8049
  _wcOverlayMinimized = false;
8115
- // Store final stats for display after generation
8116
8050
  wcState.lastGenStats = { tokIn: _wcTokIn, tokOut: _wcTokOut, seconds: _wcGenTotalTime, files: wcState.generatedFiles.length };
8117
8051
 
8118
- // Auto-save project to ~/.nha/webcraft/<projectName>/
8052
+ // Auto-save
8119
8053
  try {
8120
8054
  await fetch(API + '/api/studio/webcraft/projects/save', {
8121
- method: 'POST',
8122
- headers: {'Content-Type':'application/json'},
8055
+ method: 'POST', headers: {'Content-Type':'application/json'},
8056
+ body: JSON.stringify({ projectName: wcState.projectName, description: wcState.description, files: wcState.generatedFiles })
8057
+ });
8058
+ } catch(_) {}
8059
+
8060
+ renderWebCraft(document.getElementById('content'));
8061
+
8062
+ // Auto-repair: run immediately after generation completes
8063
+ await wcAutoRepair(filePlan, sysPreamble);
8064
+ }
8065
+
8066
+ // ── Auto-repair pass — fixes _error and _syntaxError files ────────────────
8067
+ // Called automatically after generation and available as manual button
8068
+ var _wcRepairRunning = false;
8069
+ async function wcAutoRepair(filePlan, sysPreamble) {
8070
+ if (_wcRepairRunning) return;
8071
+ // Collect broken files: LLM errors + syntax errors
8072
+ var toFix = wcState.generatedFiles.filter(function(f){ return f._error || f._syntaxError; });
8073
+ if (toFix.length === 0) return;
8074
+
8075
+ _wcRepairRunning = true;
8076
+ wcState.repairing = true;
8077
+ wcState.repairTotal = toFix.length;
8078
+ wcState.repairDone = 0;
8079
+ renderWebCraft(document.getElementById('content'));
8080
+
8081
+ // Build a map name→plan for prompt lookup
8082
+ var planMap = {};
8083
+ if (filePlan) filePlan.forEach(function(fp){ planMap[fp.name] = fp; });
8084
+
8085
+ var _nl3 = String.fromCharCode(10);
8086
+ var sysBase = sysPreamble || ('You are an expert full-stack engineer. Output ONLY the complete corrected file content. No explanations, no markdown fences.');
8087
+
8088
+ for (var ri = 0; ri < toFix.length; ri++) {
8089
+ var broken = toFix[ri];
8090
+ var plan = planMap[broken.name];
8091
+ wcState.repairDone = ri;
8092
+ wcState.repairCurrent = broken.name;
8093
+ renderWebCraft(document.getElementById('content'));
8094
+
8095
+ await new Promise(function(resolve){ setTimeout(resolve, 2000); });
8096
+ try {
8097
+ var fixSys = sysBase + _nl3 + 'You are fixing a broken or truncated file. Output ONLY the complete corrected file. No fences, no explanations.';
8098
+ var fixUser;
8099
+ if (broken._error) {
8100
+ // LLM failed entirely — regenerate from original prompt
8101
+ fixUser = plan
8102
+ ? plan.prompt + _nl3 + _nl3 + 'File to generate: ' + broken.name
8103
+ : 'Regenerate the file: ' + broken.name;
8104
+ } else {
8105
+ // Syntax error — pass existing content + error for targeted fix
8106
+ fixUser = 'File: ' + broken.name + _nl3 +
8107
+ 'Error: ' + (broken._syntaxError || 'truncated/incomplete') + _nl3 + _nl3 +
8108
+ 'Current broken content (last 800 chars shown if long):' + _nl3 +
8109
+ (broken.content.length > 800 ? broken.content.slice(0, 400) + _nl3 + '...' + _nl3 + broken.content.slice(-400) : broken.content) + _nl3 + _nl3 +
8110
+ 'Output the COMPLETE corrected file from the beginning.';
8111
+ }
8112
+ var fixed = await wcCallLLM(fixSys, fixUser, null, broken.lang || plan && plan.lang);
8113
+ var _fence3 = String.fromCharCode(96,96,96);
8114
+ var fixLines = fixed.split(_nl3);
8115
+ if (fixLines.length > 0 && fixLines[0].indexOf(_fence3) === 0) fixLines.shift();
8116
+ if (fixLines.length > 0 && fixLines[fixLines.length-1].trim() === _fence3) fixLines.pop();
8117
+ fixed = fixLines.join(_nl3).trim();
8118
+ var lang2 = broken.lang || (plan && plan.lang) || 'text';
8119
+ var check2 = wcSyntaxCheck(fixed, lang2);
8120
+ for (var gi3 = 0; gi3 < wcState.generatedFiles.length; gi3++) {
8121
+ if (wcState.generatedFiles[gi3].name === broken.name) {
8122
+ wcState.generatedFiles[gi3] = { name: broken.name, content: fixed, lang: lang2 };
8123
+ if (!check2.ok) wcState.generatedFiles[gi3]._syntaxError = check2.reason;
8124
+ break;
8125
+ }
8126
+ }
8127
+ } catch(e) { /* keep as broken */ }
8128
+
8129
+ wcState.repairDone = ri + 1;
8130
+ renderWebCraft(document.getElementById('content'));
8131
+ }
8132
+
8133
+ _wcRepairRunning = false;
8134
+ wcState.repairing = false;
8135
+ wcState.repairTotal = 0;
8136
+ wcState.repairDone = 0;
8137
+ wcState.repairCurrent = '';
8138
+
8139
+ // Save after repair
8140
+ try {
8141
+ await fetch(API + '/api/studio/webcraft/projects/save', {
8142
+ method: 'POST', headers: {'Content-Type':'application/json'},
8123
8143
  body: JSON.stringify({ projectName: wcState.projectName, description: wcState.description, files: wcState.generatedFiles })
8124
8144
  });
8125
8145
  } catch(_) {}
@@ -8127,6 +8147,12 @@ async function wcGenerate() {
8127
8147
  renderWebCraft(document.getElementById('content'));
8128
8148
  }
8129
8149
 
8150
+ // Manual trigger for repair — called from "Correggi tutti" button
8151
+ function wcTriggerRepair() {
8152
+ if (_wcRepairRunning) return;
8153
+ wcAutoRepair(_wcLastFilePlan, _wcLastSysPreamble);
8154
+ }
8155
+
8130
8156
  // Quick structural check — returns {ok, reason} without calling the LLM
8131
8157
  // Reads only structure (braces, tags) — does NOT add content to any context
8132
8158
  function wcSyntaxCheck(content, lang) {