nothumanallowed 13.5.156 → 13.5.158

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.156",
3
+ "version": "13.5.158",
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/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.156';
8
+ export const VERSION = '13.5.158';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -7362,8 +7362,7 @@ var _wcGrepOpen = false; // grep panel visible
7362
7362
  var _wcGrepQuery = '';
7363
7363
  var _updateInfo = null; // {current, latest, updateAvailable} — fetched once at boot
7364
7364
  var _wcGrepResults = [];
7365
- var _wcOverlayMinimized = false; // overlay minimized by user click
7366
- var _wcOverlayTimer = null; // inactivity timer to restore overlay
7365
+ // (overlay pill removed inline progress bar used instead)
7367
7366
  var _wcGenAbortCtrl = null; // AbortController for generation stop
7368
7367
  var _wcSyntaxResults = []; // [{file, ok, error}]
7369
7368
  var _wcSnapshots = []; // [{ts, fileCount}]
@@ -7394,22 +7393,15 @@ function wcStartGenTimer() {
7394
7393
 
7395
7394
  function wcUpdateGenOverlay(fi2, total, name) {
7396
7395
  _wcGenOverlayState = { fi: fi2, total: total, name: name };
7397
- // Update only the specific DOM nodes — no innerHTML rewrite, no flicker
7398
7396
  var pct = total > 0 ? Math.round((fi2 / total) * 100) : 0;
7399
7397
  var counterEl = document.getElementById('wcGenCounter');
7400
7398
  var barEl = document.getElementById('wcGenBar');
7401
7399
  var nameEl = document.getElementById('wcGenFileName');
7402
7400
  var timeEl = document.getElementById('wcGenTime');
7403
- var pillLabel = document.getElementById('wcPillLabel');
7404
- var pillCount = document.getElementById('wcPillCount');
7405
- var pillTime = document.getElementById('wcPillTime');
7406
7401
  if (counterEl) counterEl.textContent = fi2 + ' / ' + total;
7407
7402
  if (barEl) barEl.style.width = pct + '%';
7408
- if (nameEl) nameEl.textContent = name || '';
7403
+ if (nameEl) nameEl.textContent = name ? name.split(',')[0].trim() : '';
7409
7404
  if (timeEl) timeEl.textContent = wcGenElapsed();
7410
- if (pillLabel) pillLabel.textContent = name ? name.split(',')[0].trim() : 'Generando...';
7411
- if (pillCount) pillCount.textContent = fi2 + '/' + total;
7412
- if (pillTime) pillTime.textContent = wcGenElapsed();
7413
7405
  }
7414
7406
 
7415
7407
  // Skills state
@@ -7583,55 +7575,40 @@ function renderWebCraft(el) {
7583
7575
  : '') +
7584
7576
  '</div>' +
7585
7577
  '<div data-wc-files style="position:relative;flex:1;min-width:0;background:var(--bg2);border:1px solid var(--border);border-radius:10px;display:flex;flex-direction:column;height:100%;overflow:hidden">' +
7586
- (wcState.repairing ?
7587
- (_wcOverlayMinimized
7588
- // Minimized repair: pill bottom-right
7589
- ? '<div id="wcRepairOverlay" onclick="wcOverlayRestore()" style="position:absolute;bottom:12px;right:12px;z-index:50;background:rgba(0,0,0,0.85);border:1px solid rgba(234,179,8,0.6);border-radius:20px;padding:5px 12px;display:flex;align-items:center;gap:7px;cursor:pointer;backdrop-filter:blur(4px)">'
7590
- +'<span style="font-size:14px;animation:wcRobotBob .9s ease-in-out infinite">&#128295;</span>'
7591
- +'<span style="font-size:10px;color:#facc15;font-weight:700;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" id="wcRepairFile">'+wcEsc(wcState.repairCurrent || 'Correzione...')+'</span>'
7592
- +'<span style="font-size:9px;color:var(--dim)" id="wcRepairCounter">'+wcState.repairDone+'/'+wcState.repairTotal+'</span>'
7593
- +'<span style="display:flex;gap:3px">'+[0,1,2].map(function(_,idx){ return '<span style="width:4px;height:4px;border-radius:50%;background:#facc15;animation:wcDot 1.1s ease-in-out infinite '+(idx*0.18)+'s"></span>'; }).join('')+'</span>'
7594
- +'</div>'
7595
- // Full repair: sticky header bar — code stays visible below
7596
- : '<div id="wcRepairOverlay" style="position:absolute;top:0;left:0;right:0;z-index:50;background:rgba(20,16,0,0.92);backdrop-filter:blur(6px);border-bottom:1px solid rgba(234,179,8,0.5);padding:8px 16px;display:flex;align-items:center;gap:10px">'
7597
- +'<span style="font-size:16px;animation:wcRobotBob .9s ease-in-out infinite;flex-shrink:0">&#128295;</span>'
7598
- +'<span style="font-size:11px;font-weight:700;color:#facc15;flex-shrink:0">Correzione automatica</span>'
7599
- +'<span style="font-size:10px;color:#fde68a;font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1" id="wcRepairFile">'+wcEsc(wcState.repairCurrent || '')+'</span>'
7600
- +'<span style="font-size:10px;color:var(--dim);flex-shrink:0" id="wcRepairCounter">'+wcState.repairDone+' / '+wcState.repairTotal+' file</span>'
7601
- +'<span onclick="wcOverlayMinimize()" style="font-size:10px;color:var(--dim);cursor:pointer;flex-shrink:0;padding:2px 6px;border:1px solid var(--border2);border-radius:4px" title="Minimizza">&#8211;</span>'
7602
- +'<span style="display:flex;gap:3px">'+[0,1,2].map(function(_,idx){ return '<span style="width:4px;height:4px;border-radius:50%;background:#facc15;animation:wcDot 1.1s ease-in-out infinite '+(idx*0.18)+'s"></span>'; }).join('')+'</span>'
7603
- +'</div>'
7604
- )
7605
- : wcState.running ? (
7606
- _wcOverlayMinimized
7607
- // Minimized gen: pill bottom-right
7608
- ? '<div id="wcGenOverlay" onclick="wcOverlayRestore()" style="position:absolute;bottom:12px;right:12px;z-index:50;background:rgba(0,0,0,0.85);border:1px solid var(--green3);border-radius:20px;padding:5px 12px;display:flex;align-items:center;gap:7px;cursor:pointer;backdrop-filter:blur(4px)">'
7609
- +'<span style="font-size:14px;animation:wcRobotBob .9s ease-in-out infinite">&#129302;</span>'
7610
- +'<span id="wcPillLabel" style="font-size:10px;color:var(--green);font-weight:700;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+wcEsc((_wcGenOverlayState.name||'').split(',')[0].trim() || 'Generando...')+'</span>'
7611
- +'<span id="wcPillCount" style="font-size:9px;color:var(--dim)">'+_wcGenOverlayState.fi+'/'+_wcGenOverlayState.total+'</span>'
7612
- +'<span id="wcPillTime" style="font-size:9px;color:var(--dim)">'+wcGenElapsed()+'</span>'
7613
- +'<span style="display:flex;gap:3px">'+[0,1,2].map(function(_,idx){ return '<span style="width:4px;height:4px;border-radius:50%;background:var(--green);animation:wcDot 1.1s ease-in-out infinite '+(idx*0.18)+'s"></span>'; }).join('')+'</span>'
7614
- +'</div>'
7615
- // Full gen: sticky header bar — code streams visibly below
7616
- : '<div id="wcGenOverlay" style="position:absolute;top:0;left:0;right:0;z-index:50;background:rgba(0,14,0,0.90);backdrop-filter:blur(6px);border-bottom:1px solid var(--green3);padding:8px 16px;display:flex;flex-direction:column;gap:4px">'
7617
- +'<div style="display:flex;align-items:center;gap:10px">'
7618
- +'<span style="font-size:16px;animation:wcRobotBob .9s ease-in-out infinite;flex-shrink:0">&#129302;</span>'
7619
- +'<span style="font-size:11px;font-weight:700;color:var(--green);flex-shrink:0">Generazione in corso</span>'
7620
- +'<span id="wcGenFileName" style="font-size:10px;color:var(--dim);font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1">'+wcEsc((_wcGenOverlayState.name||'').split(',')[0].trim())+'</span>'
7621
- +'<span id="wcGenCounter" style="font-size:10px;color:var(--dim);flex-shrink:0">'+_wcGenOverlayState.fi+' / '+_wcGenOverlayState.total+'</span>'
7622
- +'<span id="wcGenTime" style="font-size:10px;color:var(--dim);flex-shrink:0">'+wcGenElapsed()+'</span>'
7623
- +'<span onclick="wcOverlayMinimize()" style="font-size:10px;color:var(--dim);cursor:pointer;flex-shrink:0;padding:2px 6px;border:1px solid var(--border2);border-radius:4px" title="Minimizza">&#8211;</span>'
7624
- +'<span style="display:flex;gap:3px">'+[0,1,2].map(function(_,idx){ return '<span style="width:4px;height:4px;border-radius:50%;background:var(--green);animation:wcDot 1.1s ease-in-out infinite '+(idx*0.18)+'s"></span>'; }).join('')+'</span>'
7625
- +'</div>'
7626
- +'<div style="height:2px;background:rgba(255,255,255,0.07);border-radius:1px;overflow:hidden">'
7627
- +'<div id="wcGenBar" style="height:100%;width:'+Math.round((_wcGenOverlayState.fi/_wcGenOverlayState.total||0)*100)+'%;background:var(--green);border-radius:1px;transition:width .3s ease"></div>'
7628
- +'</div>'
7629
- +'</div>'
7630
- ) : '') +
7578
+ // ── Tab bar: File / Sandbox ───────────────────────────────────────────
7631
7579
  '<div style="display:flex;border-bottom:1px solid var(--border);flex-shrink:0">' +
7632
7580
  '<button onclick="wcTabFiles()" style="padding:8px 16px;background:'+(wcRightTab==='preview'?'transparent':'var(--bg3)')+';border:none;border-right:1px solid var(--border);color:'+(wcRightTab==='preview'?'var(--dim)':'var(--text)')+';font-size:11px;font-weight:600;cursor:pointer">&#128196; File</button>' +
7633
7581
  '<button onclick="wcTabPreview()" style="padding:8px 16px;background:'+(wcRightTab==='preview'?'var(--bg3)':'transparent')+';border:none;color:'+(wcRightTab==='preview'?'var(--text)':'var(--dim)')+';font-size:11px;font-weight:600;cursor:pointer">&#127760; Sandbox</button>' +
7634
7582
  '</div>' +
7583
+ // ── Generation progress bar (inline, above code area) ─────────────────
7584
+ (wcState.repairing ?
7585
+ '<div id="wcRepairBar" style="flex-shrink:0;background:rgba(20,16,0,0.96);border-bottom:2px solid rgba(234,179,8,0.6);padding:6px 14px;display:flex;flex-direction:column;gap:3px">'
7586
+ +'<div style="display:flex;align-items:center;gap:8px">'
7587
+ +'<span style="font-size:13px;animation:wcRobotBob .9s ease-in-out infinite;flex-shrink:0">&#128295;</span>'
7588
+ +'<span style="font-size:10px;font-weight:700;color:#facc15;flex-shrink:0">Auto-fix</span>'
7589
+ +'<span style="font-size:10px;color:#fde68a;font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1" id="wcRepairFile">'+wcEsc(wcState.repairCurrent || '')+'</span>'
7590
+ +'<span style="font-size:10px;color:var(--dim);flex-shrink:0" id="wcRepairCounter">'+wcState.repairDone+' / '+wcState.repairTotal+'</span>'
7591
+ +'<span style="display:flex;gap:3px">'+[0,1,2].map(function(_,idx){ return '<span style="width:4px;height:4px;border-radius:50%;background:#facc15;animation:wcDot 1.1s ease-in-out infinite '+(idx*0.18)+'s"></span>'; }).join('')+'</span>'
7592
+ +'</div>'
7593
+ +'<div style="height:2px;background:rgba(255,255,255,0.07);border-radius:1px;overflow:hidden">'
7594
+ +'<div id="wcRepairProg" style="height:100%;width:'+(wcState.repairTotal>0?Math.round((wcState.repairDone/wcState.repairTotal)*100):0)+'%;background:#facc15;border-radius:1px;transition:width .3s ease"></div>'
7595
+ +'</div>'
7596
+ +'</div>'
7597
+ : wcState.running ?
7598
+ '<div id="wcGenOverlay" style="flex-shrink:0;background:rgba(0,14,0,0.96);border-bottom:2px solid var(--green3);padding:6px 14px;display:flex;flex-direction:column;gap:3px">'
7599
+ +'<div style="display:flex;align-items:center;gap:8px">'
7600
+ +'<span style="font-size:13px;animation:wcRobotBob .9s ease-in-out infinite;flex-shrink:0">&#129302;</span>'
7601
+ +'<span style="font-size:10px;font-weight:700;color:var(--green);flex-shrink:0">Generazione</span>'
7602
+ +'<span id="wcGenFileName" style="font-size:10px;color:var(--dim);font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1">'+wcEsc((_wcGenOverlayState.name||'').split(',')[0].trim())+'</span>'
7603
+ +'<span id="wcGenCounter" style="font-size:10px;color:var(--dim);flex-shrink:0">'+_wcGenOverlayState.fi+' / '+_wcGenOverlayState.total+'</span>'
7604
+ +'<span id="wcGenTime" style="font-size:10px;color:var(--dim);flex-shrink:0">'+wcGenElapsed()+'</span>'
7605
+ +'<span style="display:flex;gap:3px">'+[0,1,2].map(function(_,idx){ return '<span style="width:4px;height:4px;border-radius:50%;background:var(--green);animation:wcDot 1.1s ease-in-out infinite '+(idx*0.18)+'s"></span>'; }).join('')+'</span>'
7606
+ +'</div>'
7607
+ +'<div style="height:2px;background:rgba(255,255,255,0.07);border-radius:1px;overflow:hidden">'
7608
+ +'<div id="wcGenBar" style="height:100%;width:'+Math.round((_wcGenOverlayState.fi/_wcGenOverlayState.total||0)*100)+'%;background:var(--green);border-radius:1px;transition:width .3s ease"></div>'
7609
+ +'</div>'
7610
+ +'</div>'
7611
+ : '') +
7635
7612
  (wcRightTab === 'preview' ? wcSandboxPanelHtml() : codeHtml) +
7636
7613
  '</div>' +
7637
7614
  '</div>' +
@@ -8114,31 +8091,11 @@ function wcStopAll() {
8114
8091
  if (_wcGenAbortCtrl) { _wcGenAbortCtrl.abort(); _wcGenAbortCtrl = null; }
8115
8092
  wcState.running = false;
8116
8093
  wcChatRunning = false;
8117
- _wcOverlayMinimized = false;
8118
- if (_wcOverlayTimer) { clearTimeout(_wcOverlayTimer); _wcOverlayTimer = null; }
8119
8094
  wcChat.push({ role: 'system', text: '&#9632; Generazione interrotta.' });
8120
8095
  renderWebCraft(document.getElementById('content'));
8121
8096
  }
8122
8097
 
8123
- function wcOverlayMinimize() {
8124
- if (_wcOverlayTimer) clearTimeout(_wcOverlayTimer);
8125
- _wcOverlayMinimized = true;
8126
- renderWebCraft(document.getElementById('content'));
8127
- // Auto-restore after 30s of inactivity so user doesn't miss progress
8128
- _wcOverlayTimer = setTimeout(function() {
8129
- if (wcState.running || wcState.repairing) {
8130
- _wcOverlayMinimized = false;
8131
- renderWebCraft(document.getElementById('content'));
8132
- }
8133
- _wcOverlayTimer = null;
8134
- }, 30000);
8135
- }
8136
-
8137
- function wcOverlayRestore() {
8138
- if (_wcOverlayTimer) { clearTimeout(_wcOverlayTimer); _wcOverlayTimer = null; }
8139
- _wcOverlayMinimized = false;
8140
- renderWebCraft(document.getElementById('content'));
8141
- }
8098
+ // wcOverlayMinimize/Restore removed — overlay replaced with inline progress bar
8142
8099
 
8143
8100
  function wcRemoveAttachment(ai) {
8144
8101
  wcChatAttachments.splice(ai, 1);
@@ -8545,6 +8502,14 @@ async function wcDeleteProject(pi) {
8545
8502
  if (!confirm('Eliminare: ' + p.name + ' - ' + p.dir + ' ?')) return;
8546
8503
  await fetch(API + '/api/studio/webcraft/projects/' + encodeURIComponent(p.name), {method:'DELETE'});
8547
8504
  wcProjectsList.splice(pi, 1);
8505
+ // If the deleted project was the currently open one, reset all state
8506
+ if (wcState.projectName === p.name) {
8507
+ wcState.projectName = '';
8508
+ wcState.generatedFiles = [];
8509
+ wcState.activeFile = 0;
8510
+ wcState.description = '';
8511
+ wcChat = [];
8512
+ }
8548
8513
  renderWebCraft(document.getElementById('content'));
8549
8514
  }
8550
8515
  function wcUpdateField(i, val) { wcState.authFields[i].label = val; }
@@ -8785,7 +8750,6 @@ async function wcGenerate() {
8785
8750
  wcState.running = true;
8786
8751
  wcState.generatedFiles = [];
8787
8752
  wcState.activeFile = 0;
8788
- _wcOverlayMinimized = false;
8789
8753
  _wcGenAbortCtrl = new AbortController();
8790
8754
  renderWebCraft(document.getElementById('content'));
8791
8755
 
@@ -8889,13 +8853,40 @@ async function wcGenerate() {
8889
8853
  }
8890
8854
  var content = await wcCallLLM(sysPreamble, fp.prompt + _nl2 + _nl2 + 'File to generate: ' + fp.name, signal, fp.lang, undefined, onLiveUpdate);
8891
8855
  content = wcStripFences(content);
8892
- // Post-process package.json: fix common LLM mistakes (spaces in keys/names, duplicates)
8856
+ // Post-process: fix LLM streaming artifacts (spaces inserted inside keywords/identifiers)
8857
+ if (fp.lang === 'javascript' || fp.lang === 'typescript') {
8858
+ // Fix spaces inside JS/TS keywords that LLMs sometimes split during streaming
8859
+ var jsKeywords = ['const', 'let', 'var', 'function', 'return', 'require', 'import', 'export',
8860
+ 'class', 'extends', 'async', 'await', 'throw', 'catch', 'finally', 'typeof', 'instanceof',
8861
+ 'switch', 'default', 'continue', 'debugger', 'delete', 'module', 'exports', 'process'];
8862
+ jsKeywords.forEach(function(kw) {
8863
+ // Match keyword split across 1-3 chars with a space e.g. "con st", "re quire", "ex port"
8864
+ for (var split = 1; split < kw.length - 1; split++) {
8865
+ var broken = kw.slice(0, split) + ' ' + kw.slice(split);
8866
+ // Only replace when at word boundary (start of line or after space/punctuation)
8867
+ content = content.split(broken).join(kw);
8868
+ }
8869
+ });
8870
+ // Fix spaces inside common identifiers like "error Handler", "api Routes", "sec urityMiddleware"
8871
+ // Pattern: camelCase word split by a space before an uppercase letter
8872
+ content = content.replace(new RegExp('([a-z]) ([A-Z][a-z])', 'g'), '$1$2');
8873
+ // Fix "r equire" style splits in middle of word before a space+letter
8874
+ content = content.replace(new RegExp('\\b([a-z]{1,4}) ([a-z]{2,})', 'g'), function(m, a, b) {
8875
+ var joined = a + b;
8876
+ if (jsKeywords.indexOf(joined) !== -1) return joined;
8877
+ return m; // don't join random words
8878
+ });
8879
+ // Fix backslash-n literal artifacts from LLM
8880
+ var bsn = String.fromCharCode(92) + ' n';
8881
+ content = content.split(bsn).join('');
8882
+ var bsn2 = String.fromCharCode(92) + 'n';
8883
+ content = content.split(bsn2).join('');
8884
+ }
8885
+ // Post-process package.json: fix spaces in keys/names, duplicates
8893
8886
  if (fp.name === 'package.json' && fp.lang === 'json') {
8894
8887
  try {
8895
8888
  var pkg = JSON.parse(content);
8896
- // Fix name field
8897
8889
  if (typeof pkg.name === 'string') pkg.name = pkg.name.trim().toLowerCase().replace(/\s+/g, '-');
8898
- // Fix all dependency sections: strip spaces from keys, deduplicate
8899
8890
  ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'].forEach(function(section) {
8900
8891
  if (!pkg[section] || typeof pkg[section] !== 'object') return;
8901
8892
  var clean = {};
@@ -8906,7 +8897,7 @@ async function wcGenerate() {
8906
8897
  pkg[section] = clean;
8907
8898
  });
8908
8899
  content = JSON.stringify(pkg, null, 2);
8909
- } catch(_) { /* if JSON is already broken, leave as-is for repair to handle */ }
8900
+ } catch(_) {}
8910
8901
  }
8911
8902
  return content;
8912
8903
  }
@@ -9010,7 +9001,6 @@ async function wcGenerate() {
9010
9001
 
9011
9002
  wcState.running = false;
9012
9003
  _wcGenAbortCtrl = null;
9013
- _wcOverlayMinimized = false;
9014
9004
 
9015
9005
  // Auto-save
9016
9006
  try {
@@ -9067,7 +9057,28 @@ async function wcAutoRepair(filePlan, sysPreamble) {
9067
9057
  wcState.repairCurrent = broken.name;
9068
9058
  wcUpdateRepairOverlay();
9069
9059
 
9070
- await new Promise(function(resolve){ setTimeout(resolve, 2000); });
9060
+ // Switch active file to the one being repaired so tokens appear in the viewer
9061
+ var repairFileIdx = wcState.generatedFiles.findIndex(function(f){ return f.name === broken.name; });
9062
+ if (repairFileIdx >= 0) wcState.activeFile = repairFileIdx;
9063
+
9064
+ // "Destruction" animation: fade the existing code out in the <pre>
9065
+ (function animateWipe() {
9066
+ var pre = document.getElementById('wcLiveCode');
9067
+ if (!pre) return;
9068
+ var txt = pre.textContent;
9069
+ var len = txt.length;
9070
+ if (len === 0) return;
9071
+ var step = Math.max(1, Math.floor(len / 18));
9072
+ var remaining = len;
9073
+ var wipeInterval = setInterval(function() {
9074
+ remaining = Math.max(0, remaining - step);
9075
+ pre.style.opacity = String(remaining / len);
9076
+ pre.textContent = txt.slice(0, remaining);
9077
+ if (remaining <= 0) { clearInterval(wipeInterval); pre.style.opacity = '1'; pre.textContent = ''; }
9078
+ }, 40);
9079
+ }());
9080
+
9081
+ await new Promise(function(resolve){ setTimeout(resolve, 800); });
9071
9082
  try {
9072
9083
  var fixSys = sysBase + _nl3 + 'You are fixing a broken or truncated file. Output ONLY the complete corrected file. No fences, no explanations.';
9073
9084
  var fixUser;
@@ -9084,17 +9095,23 @@ async function wcAutoRepair(filePlan, sysPreamble) {
9084
9095
  (broken.content.length > 800 ? broken.content.slice(0, 400) + _nl3 + '...' + _nl3 + broken.content.slice(-400) : broken.content) + _nl3 + _nl3 +
9085
9096
  'Output the COMPLETE corrected file from the beginning.';
9086
9097
  }
9087
- var fixed = await wcCallLLM(fixSys, fixUser, null, broken.lang || plan && plan.lang, 8192);
9098
+ // Stream repair tokens directly into the <pre>
9099
+ var repairAccum = '';
9100
+ var repairLang2 = broken.lang || (plan && plan.lang) || 'text';
9101
+ var fixed = await wcCallLLM(fixSys, fixUser, null, repairLang2, 8192, function(tok) {
9102
+ repairAccum += tok;
9103
+ var pre2 = document.getElementById('wcLiveCode');
9104
+ if (pre2) { pre2.textContent = repairAccum; pre2.style.opacity = '1'; var cw = document.getElementById('wcCodeWrap'); if(cw) cw.scrollTop = cw.scrollHeight; }
9105
+ });
9088
9106
  var _fence3 = String.fromCharCode(96,96,96);
9089
9107
  var fixLines = fixed.split(_nl3);
9090
9108
  if (fixLines.length > 0 && fixLines[0].indexOf(_fence3) === 0) fixLines.shift();
9091
9109
  if (fixLines.length > 0 && fixLines[fixLines.length-1].trim() === _fence3) fixLines.pop();
9092
9110
  fixed = fixLines.join(_nl3).trim();
9093
- var lang2 = broken.lang || (plan && plan.lang) || 'text';
9094
- var check2 = wcSyntaxCheck(fixed, lang2);
9111
+ var check2 = wcSyntaxCheck(fixed, repairLang2);
9095
9112
  for (var gi3 = 0; gi3 < wcState.generatedFiles.length; gi3++) {
9096
9113
  if (wcState.generatedFiles[gi3].name === broken.name) {
9097
- wcState.generatedFiles[gi3] = { name: broken.name, content: fixed, lang: lang2 };
9114
+ wcState.generatedFiles[gi3] = { name: broken.name, content: fixed, lang: repairLang2 };
9098
9115
  if (!check2.ok) wcState.generatedFiles[gi3]._syntaxError = check2.reason;
9099
9116
  break;
9100
9117
  }
@@ -9126,8 +9143,10 @@ async function wcAutoRepair(filePlan, sysPreamble) {
9126
9143
  function wcUpdateRepairOverlay() {
9127
9144
  var counter = document.getElementById('wcRepairCounter');
9128
9145
  var fileEl = document.getElementById('wcRepairFile');
9129
- if (counter) counter.textContent = wcState.repairDone + ' / ' + wcState.repairTotal + ' file';
9146
+ var prog = document.getElementById('wcRepairProg');
9147
+ if (counter) counter.textContent = wcState.repairDone + ' / ' + wcState.repairTotal;
9130
9148
  if (fileEl) fileEl.textContent = wcState.repairCurrent;
9149
+ if (prog) prog.style.width = (wcState.repairTotal > 0 ? Math.round((wcState.repairDone / wcState.repairTotal) * 100) : 0) + '%';
9131
9150
  }
9132
9151
 
9133
9152
  function wcTriggerRepair() {