nothumanallowed 13.5.198 → 13.5.199

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.198",
3
+ "version": "13.5.199",
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": {
@@ -3349,6 +3349,8 @@ export async function cmdUI(args) {
3349
3349
  const body = await parseBody(req);
3350
3350
  const task = (body.task || '').trim();
3351
3351
  if (!task) { sendJSON(res, 400, { error: 'task required' }); logRequest(method, pathname, 400, Date.now() - start); return; }
3352
+ // Reload config so provider changes take effect immediately
3353
+ const config = loadConfig();
3352
3354
 
3353
3355
  const plannerLang = (() => { const LANG_MAP2 = {en:'English',it:'Italian',es:'Spanish',fr:'French',de:'German',pt:'Portuguese',zh:'Chinese',ja:'Japanese',ar:'Arabic',hi:'Hindi',ru:'Russian',nl:'Dutch',pl:'Polish',tr:'Turkish',ko:'Korean'}; const lc = (config?.language||'it').slice(0,2); return LANG_MAP2[lc]||'Italian'; })();
3354
3356
 
@@ -3574,6 +3576,9 @@ Rules:
3574
3576
  // ── Studio: run single step (SSE streaming) ──────────────────────
3575
3577
  if (pathname === '/api/studio/run' && method === 'POST') {
3576
3578
  const body = await parseBody(req, 4_194_304); // 4MB — context can be up to 120KB + task + PDF
3579
+ // Reload config on every request so provider/model/apiKey changes take effect immediately
3580
+ // (the top-level `config` is loaded once at startup and would be stale otherwise)
3581
+ const config = loadConfig();
3577
3582
  const { agent, task, context, stepDef } = body;
3578
3583
  const stepPdfBase64 = body.pdfBase64 || null;
3579
3584
  const stepPdfName = body.pdfName || null;
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.198';
8
+ export const VERSION = '13.5.199';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -5199,8 +5199,37 @@ function downloadStudioPDF() {
5199
5199
  var nodes = studioState.nodes || [];
5200
5200
  var fileName = (task).slice(0, 60).replace(/[^a-z0-9\s]/gi,'').trim().replace(/\s+/g,'-') || 'NHA-Studio';
5201
5201
 
5202
- // Always generate the full Studio PDF with all agent outputs.
5203
- // The canvas panel is already open for the HTML dashboard PDF = complete structured report.
5202
+ // When a canvas HTML report exists, print IT directly — it's already pixel-perfect with
5203
+ // charts, tables and @media print CSS. No need to rebuild from markdown.
5204
+ if (studioState.canvas) {
5205
+ var canvasHtmlForPrint = studioState.canvas;
5206
+ var btn2c = document.getElementById('studioInlinePdfBtn');
5207
+ var dlBtn2c = document.querySelector('button[onclick="downloadStudioPDF()"]');
5208
+ function setBusyC(b) {
5209
+ if (btn2c) { btn2c.disabled = b; btn2c.textContent = b ? 'Generando PDF...' : '\u2913 PDF'; }
5210
+ if (dlBtn2c) { dlBtn2c.disabled = b; dlBtn2c.textContent = b ? 'Generando PDF...' : '\u2913 Download PDF'; }
5211
+ }
5212
+ setBusyC(true);
5213
+ var oldIfrC = document.getElementById('nhaPrintFrame');
5214
+ if (oldIfrC) oldIfrC.remove();
5215
+ var ifrC = document.createElement('iframe');
5216
+ ifrC.id = 'nhaPrintFrame';
5217
+ ifrC.style.cssText = 'position:fixed;top:-9999px;left:-9999px;width:1100px;height:800px;border:none;opacity:0;pointer-events:none';
5218
+ ifrC.onload = function() {
5219
+ setTimeout(function() {
5220
+ try { ifrC.contentWindow.focus(); ifrC.contentWindow.print(); } catch(e) {}
5221
+ setBusyC(false);
5222
+ setTimeout(function(){ try { ifrC.remove(); } catch(e){} }, 8000);
5223
+ }, 2500); // wait for Chart.js charts to render
5224
+ };
5225
+ document.body.appendChild(ifrC);
5226
+ try { ifrC.contentDocument.open(); ifrC.contentDocument.write(canvasHtmlForPrint); ifrC.contentDocument.close(); }
5227
+ catch(e) { ifrC.srcdoc = canvasHtmlForPrint; }
5228
+ setTimeout(function(){ setBusyC(false); }, 8000);
5229
+ return;
5230
+ }
5231
+
5232
+ // No canvas — generate the full text-based Studio PDF from agent markdown outputs.
5204
5233
 
5205
5234
  // ── Markdown → HTML for PDF (full support: tables, lists, headers, inline) ──
5206
5235
  function mdToPdfHtml(raw) {
@@ -6712,10 +6741,10 @@ function renderStudioSessionsBar() {
6712
6741
  '</div>' +
6713
6742
  '<div style="max-height:240px;overflow-y:auto;padding-right:2px;display:flex;flex-direction:column;gap:6px">' +
6714
6743
  sessions.map(function(s,i) {
6715
- return '<div style="background:#1e293b;border:1px solid #334155;border-radius:8px;padding:10px 12px">' +
6716
- '<div style="display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:7px">' +
6717
- '<span style="font-size:11px;color:#f1f5f9;font-weight:600;line-height:1.4;flex:1">' + esc(s.task.slice(0,65)) + (s.task.length>65?'...':'') + '</span>' +
6718
- '<button onclick="deleteStudioSession('+i+')" style="flex-shrink:0;font-size:14px;line-height:1;background:none;border:none;color:#64748b;cursor:pointer;padding:0 2px" title="Delete">&times;</button>' +
6744
+ return '<div style="background:#1e293b;border:1px solid #334155;border-radius:8px;padding:10px 12px;position:relative">' +
6745
+ '<button onclick="deleteStudioSession('+i+')" style="position:absolute;top:6px;right:6px;width:24px;height:24px;display:flex;align-items:center;justify-content:center;font-size:15px;line-height:1;background:#1e293b;border:1px solid #475569;border-radius:50%;color:#94a3b8;cursor:pointer;flex-shrink:0;z-index:1" title="Elimina sessione">&times;</button>' +
6746
+ '<div style="padding-right:28px;margin-bottom:7px">' +
6747
+ '<span style="font-size:11px;color:#f1f5f9;font-weight:600;line-height:1.4">' + esc(s.task.slice(0,65)) + (s.task.length>65?'...':'') + '</span>' +
6719
6748
  '</div>' +
6720
6749
  '<div style="font-size:10px;color:#64748b;margin-bottom:8px">' + esc(s.ts) + '</div>' +
6721
6750
  '<div style="display:flex;gap:6px">' +
@@ -6960,6 +6989,16 @@ function runStudioStep(idx, node, task, context, stepDef, signal) {
6960
6989
  var st = ev.token.replace(new RegExp(\x27[\\\\r\\\\n]+\x27,\x27g\x27), \x27 \x27);
6961
6990
  // Strip surrounding brackets for display
6962
6991
  var stLabel = st.replace(new RegExp(\x27^\\\\[\x27), \x27\x27).replace(new RegExp(\x27\\\\]\\\\s*$\x27), \x27\x27).trim();
6992
+ // If there is accumulated text before this status token, render it as markdown first
6993
+ var accText = output.trim();
6994
+ if (accText && tb.getAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110)) !== null) {
6995
+ // Render markdown of accumulated text so far, then append the new status chip below
6996
+ var mdRendered = renderMd(accText);
6997
+ tb.className = \x27studio-log-entry__text md-body\x27;
6998
+ tb.removeAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110));
6999
+ // Reset output accumulator for new section (keep full output for final render)
7000
+ tb.innerHTML = \x27<div class="md-body" style="margin-bottom:8px">\x27 + mdRendered + \x27</div>\x27;
7001
+ }
6963
7002
  // Special chip for Searching
6964
7003
  var srchM = st.match(new RegExp(\x27^\\\\[Searching:\\\\s*"([^"]+)"\\\\]\\\\s*$\x27));
6965
7004
  if (srchM) {