nothumanallowed 13.2.78 → 13.2.80
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 +1 -1
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +250 -52
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.2.
|
|
3
|
+
"version": "13.2.80",
|
|
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.2.
|
|
8
|
+
export const VERSION = '13.2.80';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -81,6 +81,34 @@ function renderMd(raw) {
|
|
|
81
81
|
// Close lists on blank or non-list line
|
|
82
82
|
if (inUl) { out.push('</ul>'); inUl = false; }
|
|
83
83
|
if (inOl) { out.push('</ol>'); inOl = false; }
|
|
84
|
+
// Markdown table: line starting with | and containing at least two |
|
|
85
|
+
if (l.charAt(0) === '|' && l.lastIndexOf('|') > 0) {
|
|
86
|
+
// Separator row (---|---) — skip, handled via <thead>
|
|
87
|
+
if (/^\|[\s\-|:]+\|$/.test(l.trim())) continue;
|
|
88
|
+
var cells = l.split('|').slice(1,-1).map(function(c){ return c.trim(); });
|
|
89
|
+
// Check if next line is a separator → this is a header row
|
|
90
|
+
var nextL = lines[i+1] ? lines[i+1].trim() : '';
|
|
91
|
+
var isHeader = /^\|[\s\-|:]+\|$/.test(nextL);
|
|
92
|
+
if (isHeader) {
|
|
93
|
+
out.push('<table class="md-table"><thead><tr>' + cells.map(function(c){ return '<th>'+c+'</th>'; }).join('') + '</tr></thead><tbody>');
|
|
94
|
+
} else {
|
|
95
|
+
// Check if we need to open tbody (no header case)
|
|
96
|
+
var prevOut = out[out.length-1] || '';
|
|
97
|
+
if (prevOut.indexOf('<tbody>') === -1 && prevOut.indexOf('<tr>') === -1) {
|
|
98
|
+
out.push('<table class="md-table"><tbody>');
|
|
99
|
+
}
|
|
100
|
+
out.push('<tr>' + cells.map(function(c){ return '<td>'+c+'</td>'; }).join('') + '</tr>');
|
|
101
|
+
// Close table if next line is not a table row
|
|
102
|
+
var nextL2 = lines[i+1] ? lines[i+1].trim() : '';
|
|
103
|
+
if (!nextL2 || nextL2.charAt(0) !== '|') { out.push('</tbody></table>'); }
|
|
104
|
+
}
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// Close open table if we hit a non-table line
|
|
108
|
+
var lastOut = out[out.length-1] || '';
|
|
109
|
+
if (lastOut.indexOf('<tr>') !== -1 && lastOut.indexOf('</table>') === -1) {
|
|
110
|
+
out.push('</tbody></table>');
|
|
111
|
+
}
|
|
84
112
|
// Blockquote > text
|
|
85
113
|
var bqm = l.match(/^> (.+)/);
|
|
86
114
|
if (bqm) { out.push('<blockquote class="md-bq">'+bqm[1]+'</blockquote>'); continue; }
|
|
@@ -3250,6 +3278,8 @@ function studioReset() {
|
|
|
3250
3278
|
if (ta) ta.value = '';
|
|
3251
3279
|
var tb = document.getElementById('studioTokenBar');
|
|
3252
3280
|
if (tb) tb.textContent = '';
|
|
3281
|
+
var inlinePdfBtn = document.getElementById('studioInlinePdfBtn');
|
|
3282
|
+
if (inlinePdfBtn) inlinePdfBtn.style.display = 'none';
|
|
3253
3283
|
renderStudioNodes();
|
|
3254
3284
|
renderStudioLog();
|
|
3255
3285
|
renderStudioResult();
|
|
@@ -3388,68 +3418,221 @@ function downloadStudioPDF() {
|
|
|
3388
3418
|
return;
|
|
3389
3419
|
}
|
|
3390
3420
|
|
|
3391
|
-
//
|
|
3421
|
+
// ── Markdown → HTML for PDF (full support: tables, lists, headers, inline) ──
|
|
3392
3422
|
function mdToPdfHtml(raw) {
|
|
3393
|
-
var
|
|
3423
|
+
var NL2 = String.fromCharCode(10);
|
|
3424
|
+
var lines = raw.split(NL2);
|
|
3394
3425
|
var out = '';
|
|
3395
|
-
var
|
|
3426
|
+
var inUl = false, inOl = false, inTable = false, inTbody = false;
|
|
3427
|
+
function closeAll() {
|
|
3428
|
+
if (inUl) { out += '</ul>'; inUl = false; }
|
|
3429
|
+
if (inOl) { out += '</ol>'; inOl = false; }
|
|
3430
|
+
if (inTable) { if (inTbody) { out += '</tbody>'; inTbody = false; } out += '</table>'; inTable = false; }
|
|
3431
|
+
}
|
|
3432
|
+
function inlineFormat(t) {
|
|
3433
|
+
t = t.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
|
3434
|
+
t = t.replace(new RegExp('[*][*]([^*]+)[*][*]','g'),'<strong>$1</strong>');
|
|
3435
|
+
t = t.replace(new RegExp('[*]([^*]+)[*]','g'),'<em>$1</em>');
|
|
3436
|
+
t = t.replace(/~~([^~]+)~~/g,'<del>$1</del>');
|
|
3437
|
+
return t;
|
|
3438
|
+
}
|
|
3396
3439
|
for (var li = 0; li < lines.length; li++) {
|
|
3397
|
-
var line = lines[li]
|
|
3398
|
-
|
|
3399
|
-
//
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
if (
|
|
3405
|
-
|
|
3406
|
-
if (
|
|
3407
|
-
|
|
3408
|
-
|
|
3440
|
+
var line = lines[li];
|
|
3441
|
+
var trimmed = line.trim();
|
|
3442
|
+
// Headers
|
|
3443
|
+
if (trimmed.slice(0,4) === '### ') { closeAll(); out += '<h3>' + inlineFormat(trimmed.slice(4)) + '</h3>'; continue; }
|
|
3444
|
+
if (trimmed.slice(0,3) === '## ') { closeAll(); out += '<h2>' + inlineFormat(trimmed.slice(3)) + '</h2>'; continue; }
|
|
3445
|
+
if (trimmed.slice(0,2) === '# ') { closeAll(); out += '<h1>' + inlineFormat(trimmed.slice(2)) + '</h1>'; continue; }
|
|
3446
|
+
// Horizontal rule
|
|
3447
|
+
if (/^---+$/.test(trimmed)) { closeAll(); out += '<hr>'; continue; }
|
|
3448
|
+
// Markdown table
|
|
3449
|
+
if (trimmed.charAt(0) === '|' && trimmed.lastIndexOf('|') > 0) {
|
|
3450
|
+
// Separator row — signals end of header
|
|
3451
|
+
if (/^\|[\s\-|:]+\|$/.test(trimmed)) {
|
|
3452
|
+
if (inTable) { out += '</thead><tbody>'; inTbody = true; }
|
|
3453
|
+
continue;
|
|
3454
|
+
}
|
|
3455
|
+
var cells = trimmed.split('|').slice(1,-1).map(function(c){ return inlineFormat(c.trim()); });
|
|
3456
|
+
var nextTrimmed = lines[li+1] ? lines[li+1].trim() : '';
|
|
3457
|
+
var nextIsSep = /^\|[\s\-|:]+\|$/.test(nextTrimmed);
|
|
3458
|
+
if (!inTable) {
|
|
3459
|
+
out += '<table>';
|
|
3460
|
+
inTable = true;
|
|
3461
|
+
if (nextIsSep) { out += '<thead>'; inTbody = false; }
|
|
3462
|
+
else { out += '<tbody>'; inTbody = true; }
|
|
3463
|
+
}
|
|
3464
|
+
var tag = (!inTbody) ? 'th' : 'td';
|
|
3465
|
+
out += '<tr>' + cells.map(function(c){ return '<'+tag+'>'+c+'</'+tag+'>'; }).join('') + '</tr>';
|
|
3409
3466
|
continue;
|
|
3410
3467
|
}
|
|
3411
|
-
|
|
3412
|
-
if (
|
|
3468
|
+
// Close table if not a table row
|
|
3469
|
+
if (inTable) { if (inTbody) { out += '</tbody>'; inTbody = false; } out += '</table>'; inTable = false; }
|
|
3470
|
+
// Unordered list
|
|
3471
|
+
if (/^[\-\*] /.test(trimmed)) {
|
|
3472
|
+
if (inOl) { out += '</ol>'; inOl = false; }
|
|
3473
|
+
if (!inUl) { out += '<ul>'; inUl = true; }
|
|
3474
|
+
out += '<li>' + inlineFormat(trimmed.slice(2)) + '</li>';
|
|
3475
|
+
continue;
|
|
3476
|
+
}
|
|
3477
|
+
// Ordered list
|
|
3478
|
+
var olMatch = trimmed.match(/^\d+\. (.+)/);
|
|
3479
|
+
if (olMatch) {
|
|
3480
|
+
if (inUl) { out += '</ul>'; inUl = false; }
|
|
3481
|
+
if (!inOl) { out += '<ol>'; inOl = true; }
|
|
3482
|
+
out += '<li>' + inlineFormat(olMatch[1]) + '</li>';
|
|
3483
|
+
continue;
|
|
3484
|
+
}
|
|
3485
|
+
// Close lists
|
|
3486
|
+
if (inUl) { out += '</ul>'; inUl = false; }
|
|
3487
|
+
if (inOl) { out += '</ol>'; inOl = false; }
|
|
3488
|
+
// Blank line
|
|
3489
|
+
if (trimmed === '') { out += '<div style="height:6px"></div>'; continue; }
|
|
3490
|
+
// Paragraph
|
|
3491
|
+
out += '<p>' + inlineFormat(trimmed) + '</p>';
|
|
3413
3492
|
}
|
|
3414
|
-
|
|
3415
|
-
return
|
|
3493
|
+
closeAll();
|
|
3494
|
+
return out;
|
|
3416
3495
|
}
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3496
|
+
|
|
3497
|
+
// ── Collect workflow metadata ─────────────────────────────────────────────
|
|
3498
|
+
var activeNodes = nodes.filter(function(n){ return n.output && n.output !== '(no output)' && n.agent !== 'CanvasAgent'; });
|
|
3499
|
+
var totalTokensIn = studioTokens ? (studioTokens.in || 0) : 0;
|
|
3500
|
+
var totalTokensOut = studioTokens ? (studioTokens.out || 0) : 0;
|
|
3501
|
+
var agentNames = activeNodes.map(function(n){ return (n.icon||'') + ' ' + esc(n.label||n.agent); });
|
|
3502
|
+
var nowTime = new Date().toLocaleTimeString('it-IT', {hour:'2-digit',minute:'2-digit'});
|
|
3503
|
+
|
|
3504
|
+
// ── Section HTML ──────────────────────────────────────────────────────────
|
|
3505
|
+
var sectionsHtml = activeNodes.map(function(n, idx) {
|
|
3506
|
+
var agentColor = ['#4f46e5','#0891b2','#059669','#d97706','#dc2626','#7c3aed','#0284c7'][idx % 7];
|
|
3507
|
+
return '<div class="section">' +
|
|
3508
|
+
'<div class="agent-header" style="border-left-color:' + agentColor + '">' +
|
|
3509
|
+
'<span class="agent-icon">' + (n.icon||'■') + '</span>' +
|
|
3510
|
+
'<div><div class="agent-name">' + esc(n.label||n.agent) + '</div>' +
|
|
3511
|
+
'<div class="agent-sub">' + esc(n.agent) + ' · Step ' + (idx+1) + ' di ' + activeNodes.length + '</div></div>' +
|
|
3512
|
+
'</div>' +
|
|
3513
|
+
'<div class="section-body">' + mdToPdfHtml(n.output) + '</div>' +
|
|
3514
|
+
'</div>';
|
|
3420
3515
|
}).join('');
|
|
3421
3516
|
|
|
3422
|
-
//
|
|
3423
|
-
var
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
'
|
|
3428
|
-
'
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
'.cover
|
|
3432
|
-
'.
|
|
3433
|
-
'.
|
|
3434
|
-
'.
|
|
3435
|
-
'.
|
|
3517
|
+
// ── Full HTML document ────────────────────────────────────────────────────
|
|
3518
|
+
var html = '<!DOCTYPE html><html lang="it"><head><meta charset="UTF-8"><title>' + esc(task) + '</title>' +
|
|
3519
|
+
'<link rel="preconnect" href="https://fonts.googleapis.com">' +
|
|
3520
|
+
'<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">' +
|
|
3521
|
+
'<style>' +
|
|
3522
|
+
'*{box-sizing:border-box;margin:0;padding:0}' +
|
|
3523
|
+
'body{font-family:"Inter",system-ui,sans-serif;color:#1e1e2e;background:#fff;font-size:13px;line-height:1.7}' +
|
|
3524
|
+
|
|
3525
|
+
// Cover
|
|
3526
|
+
'.cover{background:linear-gradient(135deg,#1e1b4b 0%,#312e81 40%,#1e3a5f 100%);color:#fff;padding:64px 60px 56px;page-break-after:always;position:relative;overflow:hidden}' +
|
|
3527
|
+
'.cover::before{content:"";position:absolute;top:-80px;right:-80px;width:360px;height:360px;background:radial-gradient(circle,rgba(99,102,241,.25) 0%,transparent 70%);pointer-events:none}' +
|
|
3528
|
+
'.cover-brand{font-size:10px;font-weight:600;letter-spacing:3px;text-transform:uppercase;color:rgba(255,255,255,.5);margin-bottom:32px;display:flex;align-items:center;gap:8px}' +
|
|
3529
|
+
'.cover-brand::before{content:"";display:inline-block;width:24px;height:2px;background:#6366f1}' +
|
|
3530
|
+
'.cover h1{font-size:30px;font-weight:800;line-height:1.25;color:#fff;margin-bottom:20px;max-width:680px}' +
|
|
3531
|
+
'.cover-task-label{font-size:10px;font-weight:600;letter-spacing:2px;text-transform:uppercase;color:rgba(255,255,255,.4);margin-bottom:8px}' +
|
|
3532
|
+
'.cover-task{font-size:14px;color:rgba(255,255,255,.8);line-height:1.65;max-width:660px;font-style:italic;padding:14px 18px;background:rgba(255,255,255,.07);border-radius:8px;border-left:3px solid #6366f1}' +
|
|
3533
|
+
|
|
3534
|
+
// Stats bar
|
|
3535
|
+
'.cover-stats{display:flex;gap:0;margin-top:40px;border-top:1px solid rgba(255,255,255,.12);padding-top:28px}' +
|
|
3536
|
+
'.stat{flex:1;padding-right:28px;border-right:1px solid rgba(255,255,255,.1)}' +
|
|
3537
|
+
'.stat:last-child{border-right:none;padding-right:0;padding-left:28px}' +
|
|
3538
|
+
'.stat:not(:first-child){padding-left:28px}' +
|
|
3539
|
+
'.stat-value{font-size:22px;font-weight:800;color:#fff;line-height:1}' +
|
|
3540
|
+
'.stat-label{font-size:10px;font-weight:500;letter-spacing:1.5px;text-transform:uppercase;color:rgba(255,255,255,.45);margin-top:5px}' +
|
|
3541
|
+
|
|
3542
|
+
// Workflow bar
|
|
3543
|
+
'.workflow-bar{padding:28px 60px;background:#f8f7ff;border-bottom:1px solid #e8e5ff;display:flex;align-items:center;gap:0;flex-wrap:wrap}' +
|
|
3544
|
+
'.wf-step{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:#4f46e5;white-space:nowrap}' +
|
|
3545
|
+
'.wf-arrow{color:#c7c2f0;margin:0 6px;font-size:14px}' +
|
|
3546
|
+
'.wf-label{font-size:9px;font-weight:500;letter-spacing:1.5px;text-transform:uppercase;color:#9c97c7;margin-right:16px}' +
|
|
3547
|
+
|
|
3548
|
+
// TOC
|
|
3549
|
+
'.toc{padding:36px 60px;border-bottom:1px solid #eee;page-break-after:always}' +
|
|
3550
|
+
'.toc-title{font-size:10px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:#9ca3af;margin-bottom:18px}' +
|
|
3551
|
+
'.toc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px}' +
|
|
3552
|
+
'.toc-item{display:flex;align-items:center;gap:10px;padding:10px 14px;background:#f9f9fc;border-radius:8px;border:1px solid #ede9fe}' +
|
|
3553
|
+
'.toc-num{width:22px;height:22px;border-radius:50%;background:#4f46e5;color:#fff;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}' +
|
|
3554
|
+
'.toc-name{font-size:12px;font-weight:600;color:#1e1e2e}' +
|
|
3555
|
+
|
|
3556
|
+
// Sections
|
|
3557
|
+
'.section{padding:36px 60px;border-bottom:1px solid #f0f0f5;page-break-inside:avoid}' +
|
|
3436
3558
|
'.section:last-child{border-bottom:none}' +
|
|
3437
|
-
'.agent-
|
|
3438
|
-
'.
|
|
3439
|
-
'.
|
|
3440
|
-
'.
|
|
3441
|
-
'.section-body
|
|
3559
|
+
'.agent-header{display:flex;align-items:center;gap:14px;margin-bottom:20px;padding-left:14px;border-left:3px solid #4f46e5}' +
|
|
3560
|
+
'.agent-icon{font-size:22px;line-height:1}' +
|
|
3561
|
+
'.agent-name{font-size:14px;font-weight:700;color:#1e1e2e}' +
|
|
3562
|
+
'.agent-sub{font-size:10px;font-weight:500;color:#9ca3af;letter-spacing:.5px;margin-top:2px}' +
|
|
3563
|
+
'.section-body{font-size:13px;line-height:1.75;color:#374151}' +
|
|
3564
|
+
'.section-body h1{font-size:18px;font-weight:700;color:#1e1e2e;margin:20px 0 10px;border-bottom:1px solid #e5e7eb;padding-bottom:6px}' +
|
|
3565
|
+
'.section-body h2{font-size:15px;font-weight:700;color:#1e1e2e;margin:18px 0 8px}' +
|
|
3566
|
+
'.section-body h3{font-size:13px;font-weight:600;color:#4f46e5;margin:14px 0 6px}' +
|
|
3567
|
+
'.section-body p{margin:0 0 10px}' +
|
|
3568
|
+
'.section-body ul{margin:8px 0 10px 18px;list-style:disc}' +
|
|
3569
|
+
'.section-body ol{margin:8px 0 10px 18px}' +
|
|
3442
3570
|
'.section-body li{margin-bottom:4px}' +
|
|
3443
|
-
'.section-body strong{font-weight:700}' +
|
|
3444
|
-
'.section-body
|
|
3445
|
-
'.
|
|
3446
|
-
'.
|
|
3447
|
-
'
|
|
3571
|
+
'.section-body strong{font-weight:700;color:#1e1e2e}' +
|
|
3572
|
+
'.section-body em{color:#6366f1;font-style:italic}' +
|
|
3573
|
+
'.section-body table{width:100%;border-collapse:collapse;margin:14px 0;font-size:12px}' +
|
|
3574
|
+
'.section-body th{background:#f0eeff;color:#4f46e5;font-weight:700;text-align:left;padding:8px 12px;border:1px solid #e0d9ff;font-size:11px;letter-spacing:.3px}' +
|
|
3575
|
+
'.section-body td{padding:7px 12px;border:1px solid #ede9fe;color:#374151}' +
|
|
3576
|
+
'.section-body tr:nth-child(even) td{background:#f9f8ff}' +
|
|
3577
|
+
'.section-body hr{border:none;border-top:1px solid #e5e7eb;margin:16px 0}' +
|
|
3578
|
+
'.section-body blockquote{border-left:3px solid #6366f1;padding:8px 14px;background:#f5f3ff;border-radius:0 6px 6px 0;color:#4f46e5;font-style:italic;margin:10px 0}' +
|
|
3579
|
+
|
|
3580
|
+
// Footer
|
|
3581
|
+
'.footer-bar{padding:18px 60px;background:#f8f7ff;border-top:2px solid #e8e5ff;display:flex;justify-content:space-between;align-items:center}' +
|
|
3582
|
+
'.footer-left{font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:#9c97c7}' +
|
|
3583
|
+
'.footer-right{font-size:10px;color:#b8b4d4}' +
|
|
3584
|
+
|
|
3585
|
+
'@media print{' +
|
|
3586
|
+
'body{-webkit-print-color-adjust:exact;print-color-adjust:exact}' +
|
|
3587
|
+
'.cover{page-break-after:always}' +
|
|
3588
|
+
'.toc{page-break-after:always}' +
|
|
3589
|
+
'.section{page-break-inside:avoid}' +
|
|
3590
|
+
'}' +
|
|
3448
3591
|
'</style></head><body>' +
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
'<div class="
|
|
3592
|
+
|
|
3593
|
+
// ── Cover ────────────────────────────────────────────────────────────────
|
|
3594
|
+
'<div class="cover">' +
|
|
3595
|
+
'<div class="cover-brand">NotHumanAllowed NHA Studio</div>' +
|
|
3596
|
+
'<h1>' + esc(task.length > 90 ? task.slice(0,90)+'...' : task) + '</h1>' +
|
|
3597
|
+
'<div class="cover-task-label">Workflow richiesto</div>' +
|
|
3598
|
+
'<div class="cover-task">' + esc(task) + '</div>' +
|
|
3599
|
+
'<div class="cover-stats">' +
|
|
3600
|
+
'<div class="stat"><div class="stat-value">' + activeNodes.length + '</div><div class="stat-label">Agenti eseguiti</div></div>' +
|
|
3601
|
+
'<div class="stat"><div class="stat-value">' + today + '</div><div class="stat-label">Data generazione</div></div>' +
|
|
3602
|
+
'<div class="stat"><div class="stat-value">' + nowTime + '</div><div class="stat-label">Ora</div></div>' +
|
|
3603
|
+
(totalTokensIn > 0 ? '<div class="stat"><div class="stat-value">' + (totalTokensIn + totalTokensOut).toLocaleString() + '</div><div class="stat-label">Token totali</div></div>' : '') +
|
|
3604
|
+
'</div>' +
|
|
3605
|
+
'</div>' +
|
|
3606
|
+
|
|
3607
|
+
// ── Workflow bar ─────────────────────────────────────────────────────────
|
|
3608
|
+
'<div class="workflow-bar">' +
|
|
3609
|
+
'<span class="wf-label">Workflow:</span>' +
|
|
3610
|
+
activeNodes.map(function(n, idx){
|
|
3611
|
+
return '<span class="wf-step">' + (n.icon||'') + ' ' + esc(n.label||n.agent) + '</span>' +
|
|
3612
|
+
(idx < activeNodes.length-1 ? '<span class="wf-arrow">→</span>' : '');
|
|
3613
|
+
}).join('') +
|
|
3614
|
+
'</div>' +
|
|
3615
|
+
|
|
3616
|
+
// ── TOC ──────────────────────────────────────────────────────────────────
|
|
3617
|
+
'<div class="toc">' +
|
|
3618
|
+
'<div class="toc-title">Indice dei contenuti</div>' +
|
|
3619
|
+
'<div class="toc-grid">' +
|
|
3620
|
+
activeNodes.map(function(n, idx){
|
|
3621
|
+
return '<div class="toc-item"><div class="toc-num">' + (idx+1) + '</div><div class="toc-name">' + esc(n.label||n.agent) + '</div></div>';
|
|
3622
|
+
}).join('') +
|
|
3623
|
+
'</div>' +
|
|
3624
|
+
'</div>' +
|
|
3625
|
+
|
|
3626
|
+
// ── Sections ─────────────────────────────────────────────────────────────
|
|
3627
|
+
sectionsHtml +
|
|
3628
|
+
|
|
3629
|
+
// ── Footer ───────────────────────────────────────────────────────────────
|
|
3630
|
+
'<div class="footer-bar">' +
|
|
3631
|
+
'<span class="footer-left">NHA Studio · nothumanallowed.com</span>' +
|
|
3632
|
+
'<span class="footer-right">' + today + ' ' + nowTime +
|
|
3633
|
+
(totalTokensIn > 0 ? ' · ' + totalTokensIn.toLocaleString() + ' token in / ' + totalTokensOut.toLocaleString() + ' out' : '') +
|
|
3634
|
+
'</span>' +
|
|
3635
|
+
'</div>' +
|
|
3453
3636
|
'</body></html>';
|
|
3454
3637
|
|
|
3455
3638
|
// Use Blob URL to avoid popup blockers — opens in new tab, user can Cmd+P to print as PDF
|
|
@@ -3474,8 +3657,17 @@ function renderStudioResult() {
|
|
|
3474
3657
|
var body = hasCanvas
|
|
3475
3658
|
? '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><span style="color:var(--dim);font-size:13px">✓ ' + t('canvas_generated') + '</span><button onclick="openCanvasPanel()" style="padding:6px 14px;background:var(--greendim);border:1px solid var(--green3);border-radius:8px;color:var(--green);font-size:12px;cursor:pointer;font-weight:700">▣ ' + t('canvas_open') + '</button></div>'
|
|
3476
3659
|
: '<div class="md-body">' + renderMd(studioState.result) + '</div>';
|
|
3477
|
-
var
|
|
3478
|
-
|
|
3660
|
+
var tokLine = (studioTokens && (studioTokens.in > 0 || studioTokens.out > 0))
|
|
3661
|
+
? '<div style="margin-top:8px;font-size:11px;color:var(--dim);font-family:var(--mono)">⬆ ' + (studioTokens.in||0).toLocaleString() + ' token in ⬇ ' + (studioTokens.out||0).toLocaleString() + ' token out • <strong style="color:var(--green)">' + ((studioTokens.in||0)+(studioTokens.out||0)).toLocaleString() + '</strong> totale</div>'
|
|
3662
|
+
: '';
|
|
3663
|
+
var dlBtn = '<div style="margin-top:12px;display:flex;align-items:center;gap:10px;flex-wrap:wrap">' +
|
|
3664
|
+
'<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)">⤓ Download PDF</button>' +
|
|
3665
|
+
'<span style="font-size:11px;color:var(--dim)">Scarica il workflow completo come documento PDF</span>' +
|
|
3666
|
+
'</div>';
|
|
3667
|
+
el.innerHTML = '<div class="studio-result__title">✓ ' + t('workflow_complete') + '</div>' + body + tokLine + dlBtn;
|
|
3668
|
+
// Show/hide inline PDF button in the prompt bar
|
|
3669
|
+
var inlinePdfBtn = document.getElementById('studioInlinePdfBtn');
|
|
3670
|
+
if (inlinePdfBtn) inlinePdfBtn.style.display = 'inline-flex';
|
|
3479
3671
|
// Update canvas button style: bright green when canvas exists, dimmed otherwise
|
|
3480
3672
|
var canvasBtn = document.getElementById('studioCanvasBtn');
|
|
3481
3673
|
if (canvasBtn) {
|
|
@@ -4005,6 +4197,7 @@ function renderStudio(el) {
|
|
|
4005
4197
|
'<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' : '') + '>📎</button>' +
|
|
4006
4198
|
'<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '>' + t('run') + '</button>' +
|
|
4007
4199
|
'<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') + '">■ ' + t('stop') + '</button>' +
|
|
4200
|
+
'<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)">⤓ PDF</button>' +
|
|
4008
4201
|
'<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' : '') + '>↻</button>' +
|
|
4009
4202
|
'</div>' +
|
|
4010
4203
|
'</div>' +
|
|
@@ -4619,6 +4812,11 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
4619
4812
|
.md-body em{font-style:italic;color:var(--dim)}
|
|
4620
4813
|
.md-body del{text-decoration:line-through;color:var(--dim)}
|
|
4621
4814
|
.md-body a{color:var(--cyan);text-decoration:underline}
|
|
4815
|
+
.md-body .md-table{width:100%;border-collapse:collapse;margin:10px 0 14px;font-size:13px}
|
|
4816
|
+
.md-body .md-table th{background:var(--bg3);color:var(--bright);font-weight:600;padding:7px 12px;text-align:left;border:1px solid var(--border2);white-space:nowrap}
|
|
4817
|
+
.md-body .md-table td{padding:6px 12px;border:1px solid var(--border);color:var(--text);vertical-align:top}
|
|
4818
|
+
.md-body .md-table tbody tr:nth-child(odd){background:rgba(0,0,0,0.15)}
|
|
4819
|
+
.md-body .md-table tbody tr:hover{background:rgba(0,255,65,0.04)}
|
|
4622
4820
|
|
|
4623
4821
|
/* ---- CHAT bubble markdown tweaks ---- */
|
|
4624
4822
|
.msg--assistant .msg__bubble{white-space:normal}
|