nothumanallowed 13.2.89 → 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.89",
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.89';
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,17 +3655,72 @@ function downloadStudioPDF() {
3639
3655
  '</div>' +
3640
3656
  '</body></html>';
3641
3657
 
3642
- // Use Blob URL to avoid popup blockers opens in new tab, user can Cmd+P to print as PDF
3643
- var blob = new Blob([html], {type: 'text/html'});
3644
- var url = URL.createObjectURL(blob);
3645
- var a = document.createElement('a');
3646
- a.href = url;
3647
- a.target = '_blank';
3648
- a.download = (studioState.task || 'NHA Studio Report').slice(0, 60).replace(/[^a-z0-9\s]/gi,'').trim().replace(/\s+/g,'-') + '.html';
3649
- document.body.appendChild(a);
3650
- a.click();
3651
- document.body.removeChild(a);
3652
- setTimeout(function(){ URL.revokeObjectURL(url); }, 5000);
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();
3723
+ }
3653
3724
  }
3654
3725
 
3655
3726
  function renderStudioResult() {
@@ -3665,8 +3736,8 @@ function renderStudioResult() {
3665
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>'
3666
3737
  : '';
3667
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">' +
3668
- '<button onclick="downloadStudioPDF()" title="Scarica il workflow 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>' +
3669
- '<span style="font-size:11px;color:var(--dim)">Scarica il workflow completo come documento 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>' +
3670
3741
  '</div>';
3671
3742
  el.innerHTML = '<div class="studio-result__title">&#10003; ' + t('workflow_complete') + '</div>' + body + tokLine + dlBtn;
3672
3743
  // Show/hide inline PDF button in the prompt bar
@@ -3871,9 +3942,11 @@ async function runStudio() {
3871
3942
  var delTb2 = delL2.querySelector(\x27.studio-log-entry__text\x27);
3872
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;
3873
3944
  }
3874
- // Update Parliament pipeline node label to show current R2 agent
3945
+ // Update Parliament pipeline node show R2 agent + who it reads
3875
3946
  if (studioState.nodes[parlNodeIdx]) {
3876
- 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;
3877
3950
  studioState.nodes[parlNodeIdx].status = \x27running\x27;
3878
3951
  renderStudioNodes();
3879
3952
  }
@@ -4293,7 +4366,7 @@ function renderStudio(el) {
4293
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>' +
4294
4367
  '<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '>' + t('run') + '</button>' +
4295
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>' +
4296
- '<button id="studioInlinePdfBtn" onclick="downloadStudioPDF()" title="Scarica PDF del risultato" 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>' +
4297
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>' +
4298
4371
  '</div>' +
4299
4372
  '</div>' +