nothumanallowed 13.2.90 → 13.2.91

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.2.90",
3
+ "version": "13.2.91",
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": {
@@ -3331,7 +3331,12 @@ ${context ? `## OUTPUT FROM PREVIOUS AGENTS (use only what is RELEVANT to the wo
3331
3331
  }
3332
3332
 
3333
3333
  // Strip think tags from fullOutput before emptiness check
3334
- const fullOutputClean = fullOutput.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
3334
+ let fullOutputClean = fullOutput.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
3335
+ // Remove empty sections: headings (## N. Title) immediately followed by another heading or end-of-text
3336
+ // These appear when LLM runs out of tokens mid-response
3337
+ fullOutputClean = fullOutputClean.replace(/^(#{1,4}\s+[^\n]+)\n+(?=#{1,4}\s|$)/gm, '');
3338
+ // Also strip trailing lone headings at end of output
3339
+ fullOutputClean = fullOutputClean.replace(/(#{1,4}\s+[^\n]+)\s*$/g, '').trim();
3335
3340
 
3336
3341
  // Fallback: if LLM returned empty and we have tool data, send it directly
3337
3342
  if (!isCanvasAgent && !fullOutputClean && toolData) {
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.2.90';
8
+ export const VERSION = '13.2.91';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -3368,7 +3368,7 @@ function renderStudioNodes() {
3368
3368
  var statusLabel = {waiting:'&#9711; wait', running:'&#9654; running', done:'&#10003; done', error:'&#10005; error'}[n.status] || '';
3369
3369
  // Only animate nodes that haven't been rendered yet (first appearance)
3370
3370
  var style = n._rendered ? '' : 'animation-delay:' + (i * 110) + 'ms';
3371
- html += '<div class="' + cls + '" style="' + style + '">';
3371
+ html += '<div class="' + cls + '" data-agent-label="' + esc(n.label || n.agent) + '" style="' + style + ';cursor:pointer" onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))" title="Vai al log di ' + esc(n.label || n.agent) + '">';
3372
3372
  html += '<div class="studio-node__circle">' + n.icon + '</div>';
3373
3373
  html += '<div class="studio-node__label">' + esc(n.label) + '</div>';
3374
3374
  html += '<div class="studio-node__status studio-node__status--' + n.status + '">' + statusLabel + '</div>';
@@ -3390,6 +3390,22 @@ function renderStudioNodes() {
3390
3390
  el.innerHTML = html;
3391
3391
  }
3392
3392
 
3393
+ function studioScrollToAgent(agentLabel) {
3394
+ var logEl = document.getElementById('studioLog');
3395
+ if (!logEl) return;
3396
+ var entries = logEl.querySelectorAll('.studio-log-entry');
3397
+ var target = null;
3398
+ for (var i2 = 0; i2 < entries.length; i2++) {
3399
+ var agentSpan = entries[i2].querySelector('.studio-log-entry__agent');
3400
+ if (agentSpan && agentSpan.textContent.trim() === agentLabel) { target = entries[i2]; break; }
3401
+ }
3402
+ if (target) {
3403
+ target.scrollIntoView({behavior:'smooth', block:'start'});
3404
+ target.style.outline = '2px solid var(--green)';
3405
+ setTimeout(function(){ target.style.outline = ''; }, 1500);
3406
+ }
3407
+ }
3408
+
3393
3409
  function renderStudioLog() {
3394
3410
  var el = document.getElementById('studioLog');
3395
3411
  if (!el) return;
@@ -3639,22 +3655,72 @@ function downloadStudioPDF() {
3639
3655
  '</div>' +
3640
3656
  '</body></html>';
3641
3657
 
3642
- // Inject auto-print script so the browser shows the Print dialog immediately.
3643
- // User selects "Save as PDF" in the print dialog to get a real PDF.
3644
- var printScript = '<script>window.onload=function(){setTimeout(function(){window.print();},400);}<\/script>';
3645
- var htmlWithPrint = html.replace('</head>', printScript + '</head>');
3646
- var blob = new Blob([htmlWithPrint], {type: 'text/html'});
3647
- var url = URL.createObjectURL(blob);
3648
- // Open in new tab the page auto-triggers print dialog (user saves as PDF)
3649
- var tab = window.open(url, '_blank');
3650
- if (!tab) {
3651
- // Popup blocked fallback — download as .html with instructions
3652
- var a = document.createElement('a');
3653
- a.href = url;
3654
- a.download = (studioState.task || 'NHA Studio Report').slice(0, 60).replace(/[^a-z0-9\s]/gi,'').trim().replace(/\s+/g,'-') + '.html';
3655
- document.body.appendChild(a); a.click(); document.body.removeChild(a);
3658
+ // Generate PDF using jsPDF + html2canvas (loaded from CDN on demand)
3659
+ var pdfFileName = (studioState.task || 'NHA Studio Report').slice(0, 60).replace(/[^a-z0-9\s]/gi,'').trim().replace(/\s+/g,'-') + '.pdf';
3660
+ function doGeneratePdf() {
3661
+ var btn2 = document.getElementById('studioInlinePdfBtn');
3662
+ var dlBtn2 = document.querySelector('button[onclick="downloadStudioPDF()"]');
3663
+ function setBusy(b) {
3664
+ if (btn2) { btn2.disabled = b; btn2.textContent = b ? 'Generando PDF...' : '\u2913 PDF'; }
3665
+ if (dlBtn2) { dlBtn2.disabled = b; dlBtn2.textContent = b ? 'Generando PDF...' : '\u2913 Download PDF'; }
3666
+ }
3667
+ setBusy(true);
3668
+ // Build iframe to render the report HTML at full width
3669
+ var iframe = document.createElement('iframe');
3670
+ iframe.style.cssText = 'position:fixed;left:-9999px;top:0;width:900px;height:1px;border:none;visibility:hidden';
3671
+ document.body.appendChild(iframe);
3672
+ var ifrDoc = iframe.contentDocument || iframe.contentWindow.document;
3673
+ ifrDoc.open(); ifrDoc.write(html); ifrDoc.close();
3674
+ iframe.onload = function() {
3675
+ var body = ifrDoc.body;
3676
+ var totalH = Math.max(body.scrollHeight, body.offsetHeight, ifrDoc.documentElement.scrollHeight);
3677
+ iframe.style.height = totalH + 'px';
3678
+ window.html2canvas(body, {
3679
+ scale: 1.5, useCORS: true, allowTaint: true,
3680
+ width: 900, windowWidth: 900,
3681
+ scrollX: 0, scrollY: 0,
3682
+ ignoreElements: function(el){ return el.tagName === 'SCRIPT'; }
3683
+ }).then(function(canvas) {
3684
+ var imgData = canvas.toDataURL('image/jpeg', 0.85);
3685
+ var pdf = new window.jspdf.jsPDF({orientation:'portrait', unit:'pt', format:'a4', compress:true});
3686
+ var pageW = pdf.internal.pageSize.getWidth();
3687
+ var pageH = pdf.internal.pageSize.getHeight();
3688
+ var imgW = pageW;
3689
+ var imgH = (canvas.height * pageW) / canvas.width;
3690
+ var y = 0;
3691
+ while (y < imgH) {
3692
+ if (y > 0) pdf.addPage();
3693
+ pdf.addImage(imgData, 'JPEG', 0, -y, imgW, imgH, '', 'FAST');
3694
+ y += pageH;
3695
+ }
3696
+ pdf.save(pdfFileName);
3697
+ document.body.removeChild(iframe);
3698
+ setBusy(false);
3699
+ }).catch(function(e2) {
3700
+ document.body.removeChild(iframe);
3701
+ setBusy(false);
3702
+ alert('PDF error: ' + e2.message);
3703
+ });
3704
+ };
3705
+ }
3706
+ // Load jsPDF + html2canvas from CDN if not already loaded
3707
+ if (window.jspdf && window.html2canvas) {
3708
+ doGeneratePdf();
3709
+ } else {
3710
+ var loaded = 0;
3711
+ function onLibLoad() { loaded++; if (loaded >= 2) doGeneratePdf(); }
3712
+ if (!window.html2canvas) {
3713
+ var s1 = document.createElement('script');
3714
+ s1.src = 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';
3715
+ s1.onload = onLibLoad; document.head.appendChild(s1);
3716
+ } else { loaded++; }
3717
+ if (!window.jspdf) {
3718
+ var s2 = document.createElement('script');
3719
+ s2.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
3720
+ s2.onload = onLibLoad; document.head.appendChild(s2);
3721
+ } else { loaded++; }
3722
+ if (loaded >= 2) doGeneratePdf();
3656
3723
  }
3657
- setTimeout(function(){ URL.revokeObjectURL(url); }, 30000);
3658
3724
  }
3659
3725
 
3660
3726
  function renderStudioResult() {
@@ -3670,8 +3736,8 @@ function renderStudioResult() {
3670
3736
  ? '<div style="margin-top:8px;font-size:11px;color:var(--dim);font-family:var(--mono)">&#x2B06; ' + (studioTokens.in||0).toLocaleString() + ' token in &nbsp;&#x2B07; ' + (studioTokens.out||0).toLocaleString() + ' token out &nbsp;&#x2022;&nbsp; <strong style="color:var(--green)">' + ((studioTokens.in||0)+(studioTokens.out||0)).toLocaleString() + '</strong> totale</div>'
3671
3737
  : '';
3672
3738
  var dlBtn = '<div style="margin-top:14px;padding-top:12px;border-top:1px solid var(--border);display:flex;align-items:center;gap:10px;flex-wrap:wrap">' +
3673
- '<button onclick="downloadStudioPDF()" title="Apri il report in una nuova tab — usa Stampa > Salva come PDF" style="display:inline-flex;align-items:center;gap:6px;padding:8px 18px;background:linear-gradient(135deg,#4f46e5,#2563eb);border:none;border-radius:8px;color:#fff;font-size:12px;font-weight:600;cursor:pointer;letter-spacing:.3px;box-shadow:0 2px 8px rgba(79,70,229,.35)">&#x2913; Stampa / PDF</button>' +
3674
- '<span style="font-size:11px;color:var(--dim)">Apre il report completo usa Cmd+P &rarr; Salva come PDF</span>' +
3739
+ '<button onclick="downloadStudioPDF()" title="Genera e scarica il report come PDF" style="display:inline-flex;align-items:center;gap:6px;padding:8px 18px;background:linear-gradient(135deg,#4f46e5,#2563eb);border:none;border-radius:8px;color:#fff;font-size:12px;font-weight:600;cursor:pointer;letter-spacing:.3px;box-shadow:0 2px 8px rgba(79,70,229,.35)">&#x2913; Download PDF</button>' +
3740
+ '<span style="font-size:11px;color:var(--dim)">Scarica il report completo come file PDF</span>' +
3675
3741
  '</div>';
3676
3742
  el.innerHTML = '<div class="studio-result__title">&#10003; ' + t('workflow_complete') + '</div>' + body + tokLine + dlBtn;
3677
3743
  // Show/hide inline PDF button in the prompt bar
@@ -3876,9 +3942,11 @@ async function runStudio() {
3876
3942
  var delTb2 = delL2.querySelector(\x27.studio-log-entry__text\x27);
3877
3943
  if (delTb2) delTb2.innerHTML = \x27<span style="color:var(--green);font-family:var(--mono);font-size:10px">&#x2656; Deliberando Round 2<span class="thinking-dots"><span></span><span></span><span></span></span></span>\x27;
3878
3944
  }
3879
- // Update Parliament pipeline node label to show current R2 agent
3945
+ // Update Parliament pipeline node show R2 agent + who it reads
3880
3946
  if (studioState.nodes[parlNodeIdx]) {
3881
- studioState.nodes[parlNodeIdx].label = \x27&#x2656; \x27 + r2Label;
3947
+ var otherLabels = proposals.filter(function(p){ return (p.label || p.agent) !== r2Label; }).map(function(p){ return p.label || p.agent; });
3948
+ var readingStr = otherLabels.slice(0,2).join(\x27 + \x27) + (otherLabels.length > 2 ? \x27 +\x27 + (otherLabels.length-2) : \x27\x27);
3949
+ studioState.nodes[parlNodeIdx].label = r2Label + \x27 \u21c4 \x27 + readingStr;
3882
3950
  studioState.nodes[parlNodeIdx].status = \x27running\x27;
3883
3951
  renderStudioNodes();
3884
3952
  }
@@ -4298,7 +4366,7 @@ function renderStudio(el) {
4298
4366
  '<button onclick="document.getElementById(\\x27studioFileInput\\x27).click()" title="Attach PDF or image" style="padding:8px 10px;background:none;border:1px solid var(--border);border-radius:8px;color:var(--dim);cursor:pointer;font-size:15px" ' + (studioState.running ? 'disabled' : '') + '>&#128206;</button>' +
4299
4367
  '<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '>' + t('run') + '</button>' +
4300
4368
  '<button id="studioStopBtn" onclick="stopStudio()" title="' + t('stop') + '" style="padding:8px 14px;background:#7f1d1d;border:1px solid #ef4444;border-radius:8px;color:#ef4444;cursor:pointer;font-size:13px;font-weight:700;white-space:nowrap;' + (studioState.running ? '' : 'display:none') + '">&#9632; ' + t('stop') + '</button>' +
4301
- '<button id="studioInlinePdfBtn" onclick="downloadStudioPDF()" title="Apri report - usa Cmd+P per salvare PDF" style="display:' + (studioState.result ? 'inline-flex' : 'none') + ';align-items:center;gap:5px;padding:8px 12px;background:linear-gradient(135deg,#4f46e5,#2563eb);border:none;border-radius:8px;color:#fff;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap;box-shadow:0 2px 6px rgba(79,70,229,.35)">&#x2913; PDF</button>' +
4369
+ '<button id="studioInlinePdfBtn" onclick="downloadStudioPDF()" title="Genera e scarica il report come PDF" style="display:' + (studioState.result ? 'inline-flex' : 'none') + ';align-items:center;gap:5px;padding:8px 12px;background:linear-gradient(135deg,#4f46e5,#2563eb);border:none;border-radius:8px;color:#fff;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap;box-shadow:0 2px 6px rgba(79,70,229,.35)">&#x2913; PDF</button>' +
4302
4370
  '<button onclick="studioReset()" title="' + t('reset') + '" style="padding:8px 12px;background:none;border:1px solid var(--border);border-radius:8px;color:var(--dim);cursor:pointer;font-size:16px;line-height:1" ' + (studioState.running ? 'disabled' : '') + '>&#8635;</button>' +
4303
4371
  '</div>' +
4304
4372
  '</div>' +