nothumanallowed 13.2.78 → 13.2.79
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 +236 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.2.
|
|
3
|
+
"version": "13.2.79",
|
|
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.79';
|
|
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; }
|
|
@@ -3388,68 +3416,221 @@ function downloadStudioPDF() {
|
|
|
3388
3416
|
return;
|
|
3389
3417
|
}
|
|
3390
3418
|
|
|
3391
|
-
//
|
|
3419
|
+
// ── Markdown → HTML for PDF (full support: tables, lists, headers, inline) ──
|
|
3392
3420
|
function mdToPdfHtml(raw) {
|
|
3393
|
-
var
|
|
3421
|
+
var NL2 = String.fromCharCode(10);
|
|
3422
|
+
var lines = raw.split(NL2);
|
|
3394
3423
|
var out = '';
|
|
3395
|
-
var
|
|
3424
|
+
var inUl = false, inOl = false, inTable = false, inTbody = false;
|
|
3425
|
+
function closeAll() {
|
|
3426
|
+
if (inUl) { out += '</ul>'; inUl = false; }
|
|
3427
|
+
if (inOl) { out += '</ol>'; inOl = false; }
|
|
3428
|
+
if (inTable) { if (inTbody) { out += '</tbody>'; inTbody = false; } out += '</table>'; inTable = false; }
|
|
3429
|
+
}
|
|
3430
|
+
function inlineFormat(t) {
|
|
3431
|
+
t = t.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
|
3432
|
+
t = t.replace(new RegExp('[*][*]([^*]+)[*][*]','g'),'<strong>$1</strong>');
|
|
3433
|
+
t = t.replace(new RegExp('[*]([^*]+)[*]','g'),'<em>$1</em>');
|
|
3434
|
+
t = t.replace(/~~([^~]+)~~/g,'<del>$1</del>');
|
|
3435
|
+
return t;
|
|
3436
|
+
}
|
|
3396
3437
|
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
|
-
|
|
3438
|
+
var line = lines[li];
|
|
3439
|
+
var trimmed = line.trim();
|
|
3440
|
+
// Headers
|
|
3441
|
+
if (trimmed.slice(0,4) === '### ') { closeAll(); out += '<h3>' + inlineFormat(trimmed.slice(4)) + '</h3>'; continue; }
|
|
3442
|
+
if (trimmed.slice(0,3) === '## ') { closeAll(); out += '<h2>' + inlineFormat(trimmed.slice(3)) + '</h2>'; continue; }
|
|
3443
|
+
if (trimmed.slice(0,2) === '# ') { closeAll(); out += '<h1>' + inlineFormat(trimmed.slice(2)) + '</h1>'; continue; }
|
|
3444
|
+
// Horizontal rule
|
|
3445
|
+
if (/^---+$/.test(trimmed)) { closeAll(); out += '<hr>'; continue; }
|
|
3446
|
+
// Markdown table
|
|
3447
|
+
if (trimmed.charAt(0) === '|' && trimmed.lastIndexOf('|') > 0) {
|
|
3448
|
+
// Separator row — signals end of header
|
|
3449
|
+
if (/^\|[\s\-|:]+\|$/.test(trimmed)) {
|
|
3450
|
+
if (inTable) { out += '</thead><tbody>'; inTbody = true; }
|
|
3451
|
+
continue;
|
|
3452
|
+
}
|
|
3453
|
+
var cells = trimmed.split('|').slice(1,-1).map(function(c){ return inlineFormat(c.trim()); });
|
|
3454
|
+
var nextTrimmed = lines[li+1] ? lines[li+1].trim() : '';
|
|
3455
|
+
var nextIsSep = /^\|[\s\-|:]+\|$/.test(nextTrimmed);
|
|
3456
|
+
if (!inTable) {
|
|
3457
|
+
out += '<table>';
|
|
3458
|
+
inTable = true;
|
|
3459
|
+
if (nextIsSep) { out += '<thead>'; inTbody = false; }
|
|
3460
|
+
else { out += '<tbody>'; inTbody = true; }
|
|
3461
|
+
}
|
|
3462
|
+
var tag = (!inTbody) ? 'th' : 'td';
|
|
3463
|
+
out += '<tr>' + cells.map(function(c){ return '<'+tag+'>'+c+'</'+tag+'>'; }).join('') + '</tr>';
|
|
3409
3464
|
continue;
|
|
3410
3465
|
}
|
|
3411
|
-
|
|
3412
|
-
if (
|
|
3466
|
+
// Close table if not a table row
|
|
3467
|
+
if (inTable) { if (inTbody) { out += '</tbody>'; inTbody = false; } out += '</table>'; inTable = false; }
|
|
3468
|
+
// Unordered list
|
|
3469
|
+
if (/^[\-\*] /.test(trimmed)) {
|
|
3470
|
+
if (inOl) { out += '</ol>'; inOl = false; }
|
|
3471
|
+
if (!inUl) { out += '<ul>'; inUl = true; }
|
|
3472
|
+
out += '<li>' + inlineFormat(trimmed.slice(2)) + '</li>';
|
|
3473
|
+
continue;
|
|
3474
|
+
}
|
|
3475
|
+
// Ordered list
|
|
3476
|
+
var olMatch = trimmed.match(/^\d+\. (.+)/);
|
|
3477
|
+
if (olMatch) {
|
|
3478
|
+
if (inUl) { out += '</ul>'; inUl = false; }
|
|
3479
|
+
if (!inOl) { out += '<ol>'; inOl = true; }
|
|
3480
|
+
out += '<li>' + inlineFormat(olMatch[1]) + '</li>';
|
|
3481
|
+
continue;
|
|
3482
|
+
}
|
|
3483
|
+
// Close lists
|
|
3484
|
+
if (inUl) { out += '</ul>'; inUl = false; }
|
|
3485
|
+
if (inOl) { out += '</ol>'; inOl = false; }
|
|
3486
|
+
// Blank line
|
|
3487
|
+
if (trimmed === '') { out += '<div style="height:6px"></div>'; continue; }
|
|
3488
|
+
// Paragraph
|
|
3489
|
+
out += '<p>' + inlineFormat(trimmed) + '</p>';
|
|
3413
3490
|
}
|
|
3414
|
-
|
|
3415
|
-
return
|
|
3491
|
+
closeAll();
|
|
3492
|
+
return out;
|
|
3416
3493
|
}
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3494
|
+
|
|
3495
|
+
// ── Collect workflow metadata ─────────────────────────────────────────────
|
|
3496
|
+
var activeNodes = nodes.filter(function(n){ return n.output && n.output !== '(no output)' && n.agent !== 'CanvasAgent'; });
|
|
3497
|
+
var totalTokensIn = studioTokens ? (studioTokens.in || 0) : 0;
|
|
3498
|
+
var totalTokensOut = studioTokens ? (studioTokens.out || 0) : 0;
|
|
3499
|
+
var agentNames = activeNodes.map(function(n){ return (n.icon||'') + ' ' + esc(n.label||n.agent); });
|
|
3500
|
+
var nowTime = new Date().toLocaleTimeString('it-IT', {hour:'2-digit',minute:'2-digit'});
|
|
3501
|
+
|
|
3502
|
+
// ── Section HTML ──────────────────────────────────────────────────────────
|
|
3503
|
+
var sectionsHtml = activeNodes.map(function(n, idx) {
|
|
3504
|
+
var agentColor = ['#4f46e5','#0891b2','#059669','#d97706','#dc2626','#7c3aed','#0284c7'][idx % 7];
|
|
3505
|
+
return '<div class="section">' +
|
|
3506
|
+
'<div class="agent-header" style="border-left-color:' + agentColor + '">' +
|
|
3507
|
+
'<span class="agent-icon">' + (n.icon||'■') + '</span>' +
|
|
3508
|
+
'<div><div class="agent-name">' + esc(n.label||n.agent) + '</div>' +
|
|
3509
|
+
'<div class="agent-sub">' + esc(n.agent) + ' · Step ' + (idx+1) + ' di ' + activeNodes.length + '</div></div>' +
|
|
3510
|
+
'</div>' +
|
|
3511
|
+
'<div class="section-body">' + mdToPdfHtml(n.output) + '</div>' +
|
|
3512
|
+
'</div>';
|
|
3420
3513
|
}).join('');
|
|
3421
3514
|
|
|
3422
|
-
//
|
|
3423
|
-
var
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
'
|
|
3428
|
-
'
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
'.cover
|
|
3432
|
-
'.
|
|
3433
|
-
'.
|
|
3434
|
-
'.
|
|
3435
|
-
'.
|
|
3515
|
+
// ── Full HTML document ────────────────────────────────────────────────────
|
|
3516
|
+
var html = '<!DOCTYPE html><html lang="it"><head><meta charset="UTF-8"><title>' + esc(task) + '</title>' +
|
|
3517
|
+
'<link rel="preconnect" href="https://fonts.googleapis.com">' +
|
|
3518
|
+
'<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">' +
|
|
3519
|
+
'<style>' +
|
|
3520
|
+
'*{box-sizing:border-box;margin:0;padding:0}' +
|
|
3521
|
+
'body{font-family:"Inter",system-ui,sans-serif;color:#1e1e2e;background:#fff;font-size:13px;line-height:1.7}' +
|
|
3522
|
+
|
|
3523
|
+
// Cover
|
|
3524
|
+
'.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}' +
|
|
3525
|
+
'.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}' +
|
|
3526
|
+
'.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}' +
|
|
3527
|
+
'.cover-brand::before{content:"";display:inline-block;width:24px;height:2px;background:#6366f1}' +
|
|
3528
|
+
'.cover h1{font-size:30px;font-weight:800;line-height:1.25;color:#fff;margin-bottom:20px;max-width:680px}' +
|
|
3529
|
+
'.cover-task-label{font-size:10px;font-weight:600;letter-spacing:2px;text-transform:uppercase;color:rgba(255,255,255,.4);margin-bottom:8px}' +
|
|
3530
|
+
'.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}' +
|
|
3531
|
+
|
|
3532
|
+
// Stats bar
|
|
3533
|
+
'.cover-stats{display:flex;gap:0;margin-top:40px;border-top:1px solid rgba(255,255,255,.12);padding-top:28px}' +
|
|
3534
|
+
'.stat{flex:1;padding-right:28px;border-right:1px solid rgba(255,255,255,.1)}' +
|
|
3535
|
+
'.stat:last-child{border-right:none;padding-right:0;padding-left:28px}' +
|
|
3536
|
+
'.stat:not(:first-child){padding-left:28px}' +
|
|
3537
|
+
'.stat-value{font-size:22px;font-weight:800;color:#fff;line-height:1}' +
|
|
3538
|
+
'.stat-label{font-size:10px;font-weight:500;letter-spacing:1.5px;text-transform:uppercase;color:rgba(255,255,255,.45);margin-top:5px}' +
|
|
3539
|
+
|
|
3540
|
+
// Workflow bar
|
|
3541
|
+
'.workflow-bar{padding:28px 60px;background:#f8f7ff;border-bottom:1px solid #e8e5ff;display:flex;align-items:center;gap:0;flex-wrap:wrap}' +
|
|
3542
|
+
'.wf-step{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:#4f46e5;white-space:nowrap}' +
|
|
3543
|
+
'.wf-arrow{color:#c7c2f0;margin:0 6px;font-size:14px}' +
|
|
3544
|
+
'.wf-label{font-size:9px;font-weight:500;letter-spacing:1.5px;text-transform:uppercase;color:#9c97c7;margin-right:16px}' +
|
|
3545
|
+
|
|
3546
|
+
// TOC
|
|
3547
|
+
'.toc{padding:36px 60px;border-bottom:1px solid #eee;page-break-after:always}' +
|
|
3548
|
+
'.toc-title{font-size:10px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:#9ca3af;margin-bottom:18px}' +
|
|
3549
|
+
'.toc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px}' +
|
|
3550
|
+
'.toc-item{display:flex;align-items:center;gap:10px;padding:10px 14px;background:#f9f9fc;border-radius:8px;border:1px solid #ede9fe}' +
|
|
3551
|
+
'.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}' +
|
|
3552
|
+
'.toc-name{font-size:12px;font-weight:600;color:#1e1e2e}' +
|
|
3553
|
+
|
|
3554
|
+
// Sections
|
|
3555
|
+
'.section{padding:36px 60px;border-bottom:1px solid #f0f0f5;page-break-inside:avoid}' +
|
|
3436
3556
|
'.section:last-child{border-bottom:none}' +
|
|
3437
|
-
'.agent-
|
|
3438
|
-
'.
|
|
3439
|
-
'.
|
|
3440
|
-
'.
|
|
3441
|
-
'.section-body
|
|
3557
|
+
'.agent-header{display:flex;align-items:center;gap:14px;margin-bottom:20px;padding-left:14px;border-left:3px solid #4f46e5}' +
|
|
3558
|
+
'.agent-icon{font-size:22px;line-height:1}' +
|
|
3559
|
+
'.agent-name{font-size:14px;font-weight:700;color:#1e1e2e}' +
|
|
3560
|
+
'.agent-sub{font-size:10px;font-weight:500;color:#9ca3af;letter-spacing:.5px;margin-top:2px}' +
|
|
3561
|
+
'.section-body{font-size:13px;line-height:1.75;color:#374151}' +
|
|
3562
|
+
'.section-body h1{font-size:18px;font-weight:700;color:#1e1e2e;margin:20px 0 10px;border-bottom:1px solid #e5e7eb;padding-bottom:6px}' +
|
|
3563
|
+
'.section-body h2{font-size:15px;font-weight:700;color:#1e1e2e;margin:18px 0 8px}' +
|
|
3564
|
+
'.section-body h3{font-size:13px;font-weight:600;color:#4f46e5;margin:14px 0 6px}' +
|
|
3565
|
+
'.section-body p{margin:0 0 10px}' +
|
|
3566
|
+
'.section-body ul{margin:8px 0 10px 18px;list-style:disc}' +
|
|
3567
|
+
'.section-body ol{margin:8px 0 10px 18px}' +
|
|
3442
3568
|
'.section-body li{margin-bottom:4px}' +
|
|
3443
|
-
'.section-body strong{font-weight:700}' +
|
|
3444
|
-
'.section-body
|
|
3445
|
-
'.
|
|
3446
|
-
'.
|
|
3447
|
-
'
|
|
3569
|
+
'.section-body strong{font-weight:700;color:#1e1e2e}' +
|
|
3570
|
+
'.section-body em{color:#6366f1;font-style:italic}' +
|
|
3571
|
+
'.section-body table{width:100%;border-collapse:collapse;margin:14px 0;font-size:12px}' +
|
|
3572
|
+
'.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}' +
|
|
3573
|
+
'.section-body td{padding:7px 12px;border:1px solid #ede9fe;color:#374151}' +
|
|
3574
|
+
'.section-body tr:nth-child(even) td{background:#f9f8ff}' +
|
|
3575
|
+
'.section-body hr{border:none;border-top:1px solid #e5e7eb;margin:16px 0}' +
|
|
3576
|
+
'.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}' +
|
|
3577
|
+
|
|
3578
|
+
// Footer
|
|
3579
|
+
'.footer-bar{padding:18px 60px;background:#f8f7ff;border-top:2px solid #e8e5ff;display:flex;justify-content:space-between;align-items:center}' +
|
|
3580
|
+
'.footer-left{font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:#9c97c7}' +
|
|
3581
|
+
'.footer-right{font-size:10px;color:#b8b4d4}' +
|
|
3582
|
+
|
|
3583
|
+
'@media print{' +
|
|
3584
|
+
'body{-webkit-print-color-adjust:exact;print-color-adjust:exact}' +
|
|
3585
|
+
'.cover{page-break-after:always}' +
|
|
3586
|
+
'.toc{page-break-after:always}' +
|
|
3587
|
+
'.section{page-break-inside:avoid}' +
|
|
3588
|
+
'}' +
|
|
3448
3589
|
'</style></head><body>' +
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
'<div class="
|
|
3590
|
+
|
|
3591
|
+
// ── Cover ────────────────────────────────────────────────────────────────
|
|
3592
|
+
'<div class="cover">' +
|
|
3593
|
+
'<div class="cover-brand">NotHumanAllowed NHA Studio</div>' +
|
|
3594
|
+
'<h1>' + esc(task.length > 90 ? task.slice(0,90)+'...' : task) + '</h1>' +
|
|
3595
|
+
'<div class="cover-task-label">Workflow richiesto</div>' +
|
|
3596
|
+
'<div class="cover-task">' + esc(task) + '</div>' +
|
|
3597
|
+
'<div class="cover-stats">' +
|
|
3598
|
+
'<div class="stat"><div class="stat-value">' + activeNodes.length + '</div><div class="stat-label">Agenti eseguiti</div></div>' +
|
|
3599
|
+
'<div class="stat"><div class="stat-value">' + today + '</div><div class="stat-label">Data generazione</div></div>' +
|
|
3600
|
+
'<div class="stat"><div class="stat-value">' + nowTime + '</div><div class="stat-label">Ora</div></div>' +
|
|
3601
|
+
(totalTokensIn > 0 ? '<div class="stat"><div class="stat-value">' + (totalTokensIn + totalTokensOut).toLocaleString() + '</div><div class="stat-label">Token totali</div></div>' : '') +
|
|
3602
|
+
'</div>' +
|
|
3603
|
+
'</div>' +
|
|
3604
|
+
|
|
3605
|
+
// ── Workflow bar ─────────────────────────────────────────────────────────
|
|
3606
|
+
'<div class="workflow-bar">' +
|
|
3607
|
+
'<span class="wf-label">Workflow:</span>' +
|
|
3608
|
+
activeNodes.map(function(n, idx){
|
|
3609
|
+
return '<span class="wf-step">' + (n.icon||'') + ' ' + esc(n.label||n.agent) + '</span>' +
|
|
3610
|
+
(idx < activeNodes.length-1 ? '<span class="wf-arrow">→</span>' : '');
|
|
3611
|
+
}).join('') +
|
|
3612
|
+
'</div>' +
|
|
3613
|
+
|
|
3614
|
+
// ── TOC ──────────────────────────────────────────────────────────────────
|
|
3615
|
+
'<div class="toc">' +
|
|
3616
|
+
'<div class="toc-title">Indice dei contenuti</div>' +
|
|
3617
|
+
'<div class="toc-grid">' +
|
|
3618
|
+
activeNodes.map(function(n, idx){
|
|
3619
|
+
return '<div class="toc-item"><div class="toc-num">' + (idx+1) + '</div><div class="toc-name">' + esc(n.label||n.agent) + '</div></div>';
|
|
3620
|
+
}).join('') +
|
|
3621
|
+
'</div>' +
|
|
3622
|
+
'</div>' +
|
|
3623
|
+
|
|
3624
|
+
// ── Sections ─────────────────────────────────────────────────────────────
|
|
3625
|
+
sectionsHtml +
|
|
3626
|
+
|
|
3627
|
+
// ── Footer ───────────────────────────────────────────────────────────────
|
|
3628
|
+
'<div class="footer-bar">' +
|
|
3629
|
+
'<span class="footer-left">NHA Studio · nothumanallowed.com</span>' +
|
|
3630
|
+
'<span class="footer-right">' + today + ' ' + nowTime +
|
|
3631
|
+
(totalTokensIn > 0 ? ' · ' + totalTokensIn.toLocaleString() + ' token in / ' + totalTokensOut.toLocaleString() + ' out' : '') +
|
|
3632
|
+
'</span>' +
|
|
3633
|
+
'</div>' +
|
|
3453
3634
|
'</body></html>';
|
|
3454
3635
|
|
|
3455
3636
|
// Use Blob URL to avoid popup blockers — opens in new tab, user can Cmd+P to print as PDF
|
|
@@ -4619,6 +4800,11 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
4619
4800
|
.md-body em{font-style:italic;color:var(--dim)}
|
|
4620
4801
|
.md-body del{text-decoration:line-through;color:var(--dim)}
|
|
4621
4802
|
.md-body a{color:var(--cyan);text-decoration:underline}
|
|
4803
|
+
.md-body .md-table{width:100%;border-collapse:collapse;margin:10px 0 14px;font-size:13px}
|
|
4804
|
+
.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}
|
|
4805
|
+
.md-body .md-table td{padding:6px 12px;border:1px solid var(--border);color:var(--text);vertical-align:top}
|
|
4806
|
+
.md-body .md-table tbody tr:nth-child(odd){background:rgba(0,0,0,0.15)}
|
|
4807
|
+
.md-body .md-table tbody tr:hover{background:rgba(0,255,65,0.04)}
|
|
4622
4808
|
|
|
4623
4809
|
/* ---- CHAT bubble markdown tweaks ---- */
|
|
4624
4810
|
.msg--assistant .msg__bubble{white-space:normal}
|