nothumanallowed 13.2.92 → 13.2.94
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/commands/ui.mjs +9 -5
- package/src/constants.mjs +1 -1
- package/src/services/llm.mjs +23 -11
- package/src/services/web-ui.mjs +160 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.2.
|
|
3
|
+
"version": "13.2.94",
|
|
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/commands/ui.mjs
CHANGED
|
@@ -189,11 +189,11 @@ function sendHTML(res, html) {
|
|
|
189
189
|
res.end(html);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
function parseBody(req) {
|
|
192
|
+
function parseBody(req, maxBytes) {
|
|
193
193
|
return new Promise((resolve, reject) => {
|
|
194
194
|
const chunks = [];
|
|
195
195
|
let size = 0;
|
|
196
|
-
const MAX = 1_048_576; // 1 MB
|
|
196
|
+
const MAX = maxBytes || 1_048_576; // 1 MB default
|
|
197
197
|
req.on('data', chunk => {
|
|
198
198
|
size += chunk.length;
|
|
199
199
|
if (size > MAX) { reject(new Error('Body too large')); req.destroy(); return; }
|
|
@@ -2814,7 +2814,7 @@ export async function cmdUI(args) {
|
|
|
2814
2814
|
|
|
2815
2815
|
// ── Studio: run single step (SSE streaming) ──────────────────────
|
|
2816
2816
|
if (pathname === '/api/studio/run' && method === 'POST') {
|
|
2817
|
-
const body = await parseBody(req);
|
|
2817
|
+
const body = await parseBody(req, 4_194_304); // 4MB — context can be up to 120KB + task + PDF
|
|
2818
2818
|
const { agent, task, context, stepDef } = body;
|
|
2819
2819
|
const stepPdfBase64 = body.pdfBase64 || null;
|
|
2820
2820
|
const stepPdfName = body.pdfName || null;
|
|
@@ -3284,7 +3284,11 @@ ${context ? `## OUTPUT FROM PREVIOUS AGENTS (use only what is RELEVANT to the wo
|
|
|
3284
3284
|
let inThinkBlock = false;
|
|
3285
3285
|
let thinkBuf = '';
|
|
3286
3286
|
sendToken(isCanvasAgent ? 'Generating visual report...' : '');
|
|
3287
|
-
const llmTimeout = isCanvasAgent ?
|
|
3287
|
+
const llmTimeout = isCanvasAgent ? 180000 : 120000;
|
|
3288
|
+
// Canvas: no thinking (needs full tokens for HTML). Specialists: cap thinking to 2048 to leave room for answer.
|
|
3289
|
+
const stepLlmOpts = isCanvasAgent
|
|
3290
|
+
? { max_tokens: 12288, thinking: 'off' }
|
|
3291
|
+
: { max_tokens: 8192, thinking_budget: 2048 };
|
|
3288
3292
|
try {
|
|
3289
3293
|
await withTimeout(
|
|
3290
3294
|
callLLMStream(config, sysPrompt, userMsg,
|
|
@@ -3323,7 +3327,7 @@ ${context ? `## OUTPUT FROM PREVIOUS AGENTS (use only what is RELEVANT to the wo
|
|
|
3323
3327
|
if (stripped) sendToken(stripped);
|
|
3324
3328
|
}
|
|
3325
3329
|
},
|
|
3326
|
-
|
|
3330
|
+
stepLlmOpts,
|
|
3327
3331
|
),
|
|
3328
3332
|
llmTimeout
|
|
3329
3333
|
);
|
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.94';
|
|
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/llm.mjs
CHANGED
|
@@ -502,21 +502,33 @@ export async function callLLMStream(config, systemPrompt, userMessage, onToken,
|
|
|
502
502
|
.replace(/\|\|\(/g, '||(')
|
|
503
503
|
.replace(/\)\|\|/g, ')||');
|
|
504
504
|
|
|
505
|
+
// opts.thinking === 'off' forces thinking off regardless of config
|
|
506
|
+
// opts.max_tokens overrides the default token budget
|
|
507
|
+
const forceThinkingOff = opts.thinking === 'off' || opts.thinking === false;
|
|
508
|
+
|
|
505
509
|
let thinkingEnabled = false;
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
510
|
+
if (!forceThinkingOff) {
|
|
511
|
+
try {
|
|
512
|
+
const fs2 = await import('fs');
|
|
513
|
+
const path2 = await import('path');
|
|
514
|
+
const os2 = await import('os');
|
|
515
|
+
const cfgFile2 = path2.default.join(os2.default.homedir(), '.nha', 'config.json');
|
|
516
|
+
if (fs2.default.existsSync(cfgFile2)) {
|
|
517
|
+
const cfg2 = JSON.parse(fs2.default.readFileSync(cfgFile2, 'utf-8'));
|
|
518
|
+
thinkingEnabled = cfg2.thinking === true || cfg2.thinking === 'on' || cfg2.thinking === 'true';
|
|
519
|
+
}
|
|
520
|
+
} catch {}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Determine effective max_tokens:
|
|
524
|
+
// 1. If opts.max_tokens explicitly set, use it
|
|
525
|
+
// 2. If thinking is on, default to 8192 (need room for think + answer)
|
|
526
|
+
// 3. Otherwise default to 8192 (full context for specialist agents)
|
|
527
|
+
const effectiveMaxTokens = opts.max_tokens || (thinkingEnabled ? 8192 : 8192);
|
|
516
528
|
|
|
517
529
|
const nhaBody = {
|
|
518
530
|
model: model || '/opt/models/qwen3-32b',
|
|
519
|
-
max_tokens:
|
|
531
|
+
max_tokens: effectiveMaxTokens,
|
|
520
532
|
messages: [
|
|
521
533
|
{ role: 'system', content: sanitize(systemPrompt) },
|
|
522
534
|
{ role: 'user', content: sanitize(userMessage) },
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -3395,14 +3395,36 @@ function studioScrollToAgent(agentLabel) {
|
|
|
3395
3395
|
if (!logEl) return;
|
|
3396
3396
|
var entries = logEl.querySelectorAll('.studio-log-entry');
|
|
3397
3397
|
var target = null;
|
|
3398
|
+
var labelLow = agentLabel.toLowerCase();
|
|
3399
|
+
// Pass 1: exact match
|
|
3398
3400
|
for (var i2 = 0; i2 < entries.length; i2++) {
|
|
3399
3401
|
var agentSpan = entries[i2].querySelector('.studio-log-entry__agent');
|
|
3400
3402
|
if (agentSpan && agentSpan.textContent.trim() === agentLabel) { target = entries[i2]; break; }
|
|
3401
3403
|
}
|
|
3404
|
+
// Pass 2: startsWith (handles Parliament label that changes to "ATHENA ⇄ ...")
|
|
3405
|
+
if (!target) {
|
|
3406
|
+
for (var i3 = 0; i3 < entries.length; i3++) {
|
|
3407
|
+
var sp = entries[i3].querySelector('.studio-log-entry__agent');
|
|
3408
|
+
if (sp && (sp.textContent.trim().toLowerCase().indexOf(labelLow) === 0 || labelLow.indexOf(sp.textContent.trim().toLowerCase()) === 0)) { target = entries[i3]; break; }
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
// Pass 3: contains (for Parliament: "Parlamento" matches any log entry with that word)
|
|
3412
|
+
if (!target) {
|
|
3413
|
+
for (var i4 = 0; i4 < entries.length; i4++) {
|
|
3414
|
+
var sp2 = entries[i4].querySelector('.studio-log-entry__agent');
|
|
3415
|
+
if (sp2 && sp2.textContent.trim().toLowerCase().indexOf(labelLow.slice(0,8)) >= 0) { target = entries[i4]; break; }
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3402
3418
|
if (target) {
|
|
3403
|
-
|
|
3419
|
+
var logContainer = document.querySelector('.studio-log');
|
|
3420
|
+
if (logContainer) {
|
|
3421
|
+
var entryTop = target.offsetTop - logContainer.offsetTop;
|
|
3422
|
+
logContainer.scrollTo({top: entryTop - 8, behavior: 'smooth'});
|
|
3423
|
+
} else {
|
|
3424
|
+
target.scrollIntoView({behavior:'smooth', block:'start'});
|
|
3425
|
+
}
|
|
3404
3426
|
target.style.outline = '2px solid var(--green)';
|
|
3405
|
-
setTimeout(function(){ target.style.outline = ''; },
|
|
3427
|
+
setTimeout(function(){ target.style.outline = ''; }, 1800);
|
|
3406
3428
|
}
|
|
3407
3429
|
}
|
|
3408
3430
|
|
|
@@ -3655,7 +3677,8 @@ function downloadStudioPDF() {
|
|
|
3655
3677
|
'</div>' +
|
|
3656
3678
|
'</body></html>';
|
|
3657
3679
|
|
|
3658
|
-
// Generate PDF
|
|
3680
|
+
// Generate PDF — injects print-safe CSS then uses html2canvas at 2.5x for crisp output.
|
|
3681
|
+
// Page breaks are avoided inside .section/.card/.priority-item by injecting break-inside:avoid.
|
|
3659
3682
|
var pdfFileName = (studioState.task || 'NHA Studio Report').slice(0, 60).replace(/[^a-z0-9\s]/gi,'').trim().replace(/\s+/g,'-') + '.pdf';
|
|
3660
3683
|
function doGeneratePdf() {
|
|
3661
3684
|
var btn2 = document.getElementById('studioInlinePdfBtn');
|
|
@@ -3665,33 +3688,67 @@ function downloadStudioPDF() {
|
|
|
3665
3688
|
if (dlBtn2) { dlBtn2.disabled = b; dlBtn2.textContent = b ? 'Generando PDF...' : '\u2913 Download PDF'; }
|
|
3666
3689
|
}
|
|
3667
3690
|
setBusy(true);
|
|
3668
|
-
|
|
3691
|
+
|
|
3692
|
+
// Inject page-break-safe CSS into the HTML before rendering
|
|
3693
|
+
var printCss = '<style>body{padding:20px!important;max-width:800px!important;margin:0 auto!important}' +
|
|
3694
|
+
'.section,.card,.priority-item,.source-item,.bar-row{break-inside:avoid;page-break-inside:avoid}' +
|
|
3695
|
+
'.header{break-after:avoid;page-break-after:avoid}' +
|
|
3696
|
+
'h1,h2,h3,h4{break-after:avoid;page-break-after:avoid}' +
|
|
3697
|
+
'@media print{body{background:#fff!important;color:#111!important}' +
|
|
3698
|
+
'.header{background:linear-gradient(135deg,#4f46e5,#06b6d4)!important;-webkit-print-color-adjust:exact}' +
|
|
3699
|
+
'.section{background:#f8f9fa!important;border:1px solid #e0e0e0!important}' +
|
|
3700
|
+
'.section-title{color:#4f46e5!important}}</style>';
|
|
3701
|
+
var pdfHtml = html.replace('</head>', printCss + '</head>');
|
|
3702
|
+
|
|
3703
|
+
// Build hidden iframe at 800px (A4 equivalent at 96dpi)
|
|
3669
3704
|
var iframe = document.createElement('iframe');
|
|
3670
|
-
iframe.style.cssText = 'position:fixed;left:-9999px;top:0;width:
|
|
3705
|
+
iframe.style.cssText = 'position:fixed;left:-9999px;top:0;width:800px;height:1px;border:none;visibility:hidden';
|
|
3671
3706
|
document.body.appendChild(iframe);
|
|
3672
3707
|
var ifrDoc = iframe.contentDocument || iframe.contentWindow.document;
|
|
3673
|
-
ifrDoc.open(); ifrDoc.write(
|
|
3708
|
+
ifrDoc.open(); ifrDoc.write(pdfHtml); ifrDoc.close();
|
|
3674
3709
|
iframe.onload = function() {
|
|
3675
3710
|
var body = ifrDoc.body;
|
|
3676
3711
|
var totalH = Math.max(body.scrollHeight, body.offsetHeight, ifrDoc.documentElement.scrollHeight);
|
|
3677
3712
|
iframe.style.height = totalH + 'px';
|
|
3713
|
+
// Render at 2.5x scale for crisp text
|
|
3678
3714
|
window.html2canvas(body, {
|
|
3679
|
-
scale:
|
|
3680
|
-
|
|
3715
|
+
scale: 2.5, useCORS: true, allowTaint: true,
|
|
3716
|
+
backgroundColor: '#0d0d14',
|
|
3717
|
+
width: 800, windowWidth: 800,
|
|
3681
3718
|
scrollX: 0, scrollY: 0,
|
|
3682
3719
|
ignoreElements: function(el){ return el.tagName === 'SCRIPT'; }
|
|
3683
3720
|
}).then(function(canvas) {
|
|
3684
|
-
var imgData = canvas.toDataURL('image/
|
|
3721
|
+
var imgData = canvas.toDataURL('image/png'); // PNG for crisp text
|
|
3685
3722
|
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
|
|
3689
|
-
var
|
|
3690
|
-
var
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3723
|
+
var pageW = pdf.internal.pageSize.getWidth(); // 595pt
|
|
3724
|
+
var pageH = pdf.internal.pageSize.getHeight(); // 842pt
|
|
3725
|
+
var margin = 24; // pt
|
|
3726
|
+
var usableW = pageW - margin * 2;
|
|
3727
|
+
var usableH = pageH - margin * 2;
|
|
3728
|
+
// Scale image to fit page width
|
|
3729
|
+
var imgW = usableW;
|
|
3730
|
+
var imgH = (canvas.height * usableW) / canvas.width;
|
|
3731
|
+
|
|
3732
|
+
// Smart paging: find safe cut points every ~usableH
|
|
3733
|
+
// Strategy: render slice by slice, each slice fits one page
|
|
3734
|
+
var sliceH = Math.floor(canvas.height * (usableH / imgH)); // canvas px per page
|
|
3735
|
+
var yCanvas = 0;
|
|
3736
|
+
var pageNum = 0;
|
|
3737
|
+
while (yCanvas < canvas.height) {
|
|
3738
|
+
if (pageNum > 0) pdf.addPage();
|
|
3739
|
+
var remaining = canvas.height - yCanvas;
|
|
3740
|
+
var thisSlice = Math.min(sliceH, remaining);
|
|
3741
|
+
// Create a temporary canvas for this slice
|
|
3742
|
+
var sliceCanvas = document.createElement('canvas');
|
|
3743
|
+
sliceCanvas.width = canvas.width;
|
|
3744
|
+
sliceCanvas.height = thisSlice;
|
|
3745
|
+
var ctx = sliceCanvas.getContext('2d');
|
|
3746
|
+
ctx.drawImage(canvas, 0, yCanvas, canvas.width, thisSlice, 0, 0, canvas.width, thisSlice);
|
|
3747
|
+
var sliceData = sliceCanvas.toDataURL('image/png');
|
|
3748
|
+
var sliceImgH = (thisSlice * usableW) / canvas.width;
|
|
3749
|
+
pdf.addImage(sliceData, 'PNG', margin, margin, usableW, sliceImgH, '', 'FAST');
|
|
3750
|
+
yCanvas += thisSlice;
|
|
3751
|
+
pageNum++;
|
|
3695
3752
|
}
|
|
3696
3753
|
pdf.save(pdfFileName);
|
|
3697
3754
|
document.body.removeChild(iframe);
|
|
@@ -3781,6 +3838,8 @@ async function runStudio() {
|
|
|
3781
3838
|
studioState.running = true;
|
|
3782
3839
|
studioState.planned = false;
|
|
3783
3840
|
// Keep attachmentContext — it was loaded before hitting Run
|
|
3841
|
+
var parlBlockEl = document.getElementById('studioParliamentBlock');
|
|
3842
|
+
if (parlBlockEl) parlBlockEl.style.display = 'none';
|
|
3784
3843
|
renderStudioNodes();
|
|
3785
3844
|
renderStudioLog();
|
|
3786
3845
|
renderStudioResult();
|
|
@@ -3907,6 +3966,38 @@ async function runStudio() {
|
|
|
3907
3966
|
var parlNodeIdx = studioState.nodes.length;
|
|
3908
3967
|
studioState.nodes.push({icon:\x27♖\x27, agent:\x27Parliament\x27, label:\x27Parlamento\x27, status:\x27running\x27, output:\x27\x27, _rendered:false});
|
|
3909
3968
|
renderStudioNodes();
|
|
3969
|
+
|
|
3970
|
+
// ── Parliament visual block ──────────────────────────────────────
|
|
3971
|
+
// Track active R2 agent for visual block
|
|
3972
|
+
var parlActiveAgent = null;
|
|
3973
|
+
var parlDoneAgents = {};
|
|
3974
|
+
|
|
3975
|
+
function renderParlBlock(phase, activeLabel, convergence) {
|
|
3976
|
+
var pb = document.getElementById(\x27studioParliamentBlock\x27);
|
|
3977
|
+
if (!pb) return;
|
|
3978
|
+
pb.style.display = \x27block\x27;
|
|
3979
|
+
var agentCircles = proposals.map(function(p) {
|
|
3980
|
+
var lbl = p.label || p.agent;
|
|
3981
|
+
var isDone = !!parlDoneAgents[lbl];
|
|
3982
|
+
var isActive = lbl === activeLabel;
|
|
3983
|
+
var circCls = \x27studio-parliament__agent-circle\x27 + (isActive ? \x27 studio-parliament__agent-circle--reading\x27 : isDone ? \x27 studio-parliament__agent-circle--done\x27 : \x27\x27);
|
|
3984
|
+
var readingTxt = isActive
|
|
3985
|
+
? (\x27<div class="studio-parliament__reading">\u21c4 legge ' + proposals.filter(function(x){return (x.label||x.agent)!==lbl;}).map(function(x){return x.label||x.agent;}).slice(0,2).join(\x27, \x27) + \x27</div>\x27)
|
|
3986
|
+
: \x27\x27;
|
|
3987
|
+
return \x27<div class="studio-parliament__agent"><div class="\x27 + circCls + \x27">\x27 + esc(p.icon||String.fromCharCode(9632)) + \x27</div><div class="studio-parliament__agent-label">\x27 + esc(lbl.slice(0,14)) + \x27</div>\x27 + readingTxt + \x27</div>\x27;
|
|
3988
|
+
}).join(\x27<div class="studio-parliament__bidir">\u21c4</div>\x27);
|
|
3989
|
+
|
|
3990
|
+
var phaseLabel = phase === \x27r1\x27 ? \x27Round 1\x27 : phase === \x27r2\x27 ? \x27Round 2 — Cross-reading\x27 : phase === \x27r3\x27 ? \x27Round 3 — Mediazione\x27 : \x27Completato\x27;
|
|
3991
|
+
var roundEl = convergence != null
|
|
3992
|
+
? \x27<div class="studio-parliament__convergence">✔ Convergenza: \x27 + convergence + \x27% — deliberazione completata</div>\x27
|
|
3993
|
+
: \x27<span class="studio-parliament__round">\x27 + phaseLabel + \x27</span>\x27;
|
|
3994
|
+
|
|
3995
|
+
pb.innerHTML = \x27<div class="studio-parliament"><div class="studio-parliament__header"><div class="studio-parliament__master"><span class="studio-parliament__master-icon">♦</span><span>MASTER AGENT — Orchestrazione</span></div><div class="studio-parliament__title">♖ PARLIAMENT</div>\x27 + (convergence == null ? roundEl : \x27\x27) + \x27</div><div class="studio-parliament__agents">\x27 + agentCircles + \x27</div>\x27 + (convergence != null ? roundEl : \x27\x27) + \x27</div>\x27;
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3998
|
+
// Show initial R1 block
|
|
3999
|
+
renderParlBlock(\x27r1\x27, null, null);
|
|
4000
|
+
|
|
3910
4001
|
var deliberateBody = JSON.stringify({task: task, proposals: proposals, language: document.getElementById(\x27langSelect\x27) ? document.getElementById(\x27langSelect\x27).value : \x27it\x27});
|
|
3911
4002
|
try {
|
|
3912
4003
|
var delRes = await fetch(\x27/api/studio/deliberate\x27, {method:\x27POST\x27, headers:{\x27Content-Type\x27:\x27application/json\x27}, body: deliberateBody, signal: studioAbortController ? studioAbortController.signal : undefined});
|
|
@@ -3928,12 +4019,11 @@ async function runStudio() {
|
|
|
3928
4019
|
try {
|
|
3929
4020
|
var dev = JSON.parse(dd);
|
|
3930
4021
|
if (dev.token) {
|
|
3931
|
-
// Status tokens — check for Round 2 start to add new animated log entry
|
|
3932
4022
|
var r2StartM = dev.token.match(/^\\[Round 2: (.+?)\\]\\s*$/);
|
|
3933
4023
|
var r2LiveM = dev.token.match(/^\\[Round 2 (.+?): (\\d+) token\\]\\s*$/);
|
|
3934
4024
|
if (r2StartM) {
|
|
3935
|
-
// New R2 agent starting — add a new log entry with thinking animation
|
|
3936
4025
|
var r2Label = r2StartM[1];
|
|
4026
|
+
parlActiveAgent = r2Label;
|
|
3937
4027
|
studioLog(r2Label, \x27♖\x27, \x27\x27, \x27agent\x27, false);
|
|
3938
4028
|
var delEnts2 = document.querySelectorAll(\x27.studio-log-entry\x27);
|
|
3939
4029
|
var delL2 = delEnts2[delEnts2.length - 1];
|
|
@@ -3942,7 +4032,7 @@ async function runStudio() {
|
|
|
3942
4032
|
var delTb2 = delL2.querySelector(\x27.studio-log-entry__text\x27);
|
|
3943
4033
|
if (delTb2) delTb2.innerHTML = \x27<span style="color:var(--green);font-family:var(--mono);font-size:10px">♖ Deliberando Round 2<span class="thinking-dots"><span></span><span></span><span></span></span></span>\x27;
|
|
3944
4034
|
}
|
|
3945
|
-
|
|
4035
|
+
renderParlBlock(\x27r2\x27, r2Label, null);
|
|
3946
4036
|
if (studioState.nodes[parlNodeIdx]) {
|
|
3947
4037
|
var otherLabels = proposals.filter(function(p){ return (p.label || p.agent) !== r2Label; }).map(function(p){ return p.label || p.agent; });
|
|
3948
4038
|
var readingStr = otherLabels.slice(0,2).join(\x27 + \x27) + (otherLabels.length > 2 ? \x27 +\x27 + (otherLabels.length-2) : \x27\x27);
|
|
@@ -3951,7 +4041,6 @@ async function runStudio() {
|
|
|
3951
4041
|
renderStudioNodes();
|
|
3952
4042
|
}
|
|
3953
4043
|
} else if (r2LiveM) {
|
|
3954
|
-
// Live token count update for the current R2 agent
|
|
3955
4044
|
var r2AgentName = r2LiveM[1];
|
|
3956
4045
|
var r2Toks = parseInt(r2LiveM[2], 10);
|
|
3957
4046
|
var delAllEnts = document.querySelectorAll(\x27[data-r2-agent]\x27);
|
|
@@ -3959,35 +4048,31 @@ async function runStudio() {
|
|
|
3959
4048
|
for (var rei = delAllEnts.length - 1; rei >= 0; rei--) {
|
|
3960
4049
|
if (delAllEnts[rei].getAttribute(\x27data-r2-agent\x27) === r2AgentName) { r2Entry = delAllEnts[rei]; break; }
|
|
3961
4050
|
}
|
|
3962
|
-
if (!r2Entry) {
|
|
3963
|
-
var delAllE = document.querySelectorAll(\x27.studio-log-entry\x27);
|
|
3964
|
-
r2Entry = delAllE[delAllE.length - 1];
|
|
3965
|
-
}
|
|
4051
|
+
if (!r2Entry) { var delAllE = document.querySelectorAll(\x27.studio-log-entry\x27); r2Entry = delAllE[delAllE.length - 1]; }
|
|
3966
4052
|
if (r2Entry) {
|
|
3967
4053
|
var r2Tb = r2Entry.querySelector(\x27.studio-log-entry__text\x27);
|
|
3968
4054
|
if (r2Tb) r2Tb.innerHTML = \x27<span style="color:var(--green);font-family:var(--mono);font-size:10px">♖ Deliberando Round 2 \u2014 \x27 + r2Toks + \x27 token<span class="thinking-dots"><span></span><span></span><span></span></span></span>\x27;
|
|
3969
4055
|
}
|
|
3970
|
-
studioAddTokens(0, 20);
|
|
4056
|
+
studioAddTokens(0, 20);
|
|
3971
4057
|
} else {
|
|
3972
|
-
// Other status tokens — update last log entry
|
|
3973
4058
|
var delEntries = document.querySelectorAll(\x27.studio-log-entry\x27);
|
|
3974
4059
|
var delLast = delEntries[delEntries.length - 1];
|
|
3975
4060
|
if (delLast) { var delTb = delLast.querySelector(\x27.studio-log-entry__text\x27); if (delTb) delTb.textContent = dev.token.replace(new RegExp(\x27[\\r\\n]+\x27,\x27g\x27),\x27 \x27); }
|
|
3976
4061
|
}
|
|
3977
4062
|
} else if (dev.deliberation_r2) {
|
|
3978
4063
|
var r2d = dev.deliberation_r2;
|
|
3979
|
-
// Full output in log — no truncation
|
|
3980
4064
|
studioLog(r2d.label || r2d.agent, \x27♖\x27, \x27[R2] \x27 + (r2d.output || \x27\x27), \x27agent\x27, true);
|
|
3981
4065
|
var ni2 = studioState.nodes.findIndex(function(x){return x.agent===r2d.agent;});
|
|
3982
|
-
if (ni2 >= 0) {
|
|
3983
|
-
studioState.nodes[ni2].output = r2d.output;
|
|
3984
|
-
studioState.nodes[ni2].status = \x27done\x27;
|
|
3985
|
-
}
|
|
3986
|
-
// Estimate tokens for R2 (approx 1 token ≈ 4 chars)
|
|
4066
|
+
if (ni2 >= 0) { studioState.nodes[ni2].output = r2d.output; studioState.nodes[ni2].status = \x27done\x27; }
|
|
3987
4067
|
studioAddTokens(0, Math.ceil((r2d.output||'').length / 4));
|
|
4068
|
+
// Mark this agent done in parliament block
|
|
4069
|
+
parlDoneAgents[r2d.label || r2d.agent] = true;
|
|
4070
|
+
parlActiveAgent = null;
|
|
4071
|
+
renderParlBlock(\x27r2\x27, null, null);
|
|
3988
4072
|
renderStudioNodes();
|
|
3989
4073
|
context = r2d.output || context;
|
|
3990
4074
|
} else if (dev.deliberation_r3) {
|
|
4075
|
+
renderParlBlock(\x27r3\x27, null, null);
|
|
3991
4076
|
studioLog(\x27HERALD\x27, \x27🔧\x27, \x27[Mediazione] \x27 + (dev.deliberation_r3.output || \x27\x27), \x27system\x27, true);
|
|
3992
4077
|
studioAddTokens(0, Math.ceil((dev.deliberation_r3.output||'').length / 4));
|
|
3993
4078
|
context = dev.deliberation_r3.output || context;
|
|
@@ -3995,6 +4080,7 @@ async function runStudio() {
|
|
|
3995
4080
|
var r2Conv = Math.round((dev.r2_convergence || 0) * 100);
|
|
3996
4081
|
studioLog(\x27Parlamento\x27, \x27♖\x27, \x27Deliberazione completa — convergenza R2: \x27 + r2Conv + \x27%\x27, \x27system\x27);
|
|
3997
4082
|
if (dev.mediation) { context = dev.mediation; }
|
|
4083
|
+
renderParlBlock(\x27done\x27, null, r2Conv);
|
|
3998
4084
|
if (studioState.nodes[parlNodeIdx]) {
|
|
3999
4085
|
studioState.nodes[parlNodeIdx].status = \x27done\x27;
|
|
4000
4086
|
studioState.nodes[parlNodeIdx].label = \x27Parlamento (\x27 + r2Conv + \x27%)\x27;
|
|
@@ -4011,6 +4097,7 @@ async function runStudio() {
|
|
|
4011
4097
|
} catch(e3) {
|
|
4012
4098
|
if (e3.name !== \x27AbortError\x27) {
|
|
4013
4099
|
studioLog(\x27Parlamento\x27, \x27♖\x27, \x27Deliberazione non disponibile: \x27 + (e3.message || String(e3)), \x27error\x27);
|
|
4100
|
+
var pb2 = document.getElementById(\x27studioParliamentBlock\x27); if (pb2) pb2.style.display = \x27none\x27;
|
|
4014
4101
|
}
|
|
4015
4102
|
}
|
|
4016
4103
|
}
|
|
@@ -4046,6 +4133,7 @@ function saveStudioSession(task, nodes, log, result) {
|
|
|
4046
4133
|
task: task,
|
|
4047
4134
|
nodes: nodes.map(function(n){return {label:n.label,icon:n.icon,agent:n.agent};}),
|
|
4048
4135
|
result: result,
|
|
4136
|
+
canvas: studioState.canvas || null,
|
|
4049
4137
|
log: log.map(function(e){return {agent:e.agent,icon:e.icon,text:e.text,type:e.type,time:e.time};}),
|
|
4050
4138
|
ts: new Date().toLocaleString()
|
|
4051
4139
|
});
|
|
@@ -4089,10 +4177,28 @@ function restoreStudioSession(idx) {
|
|
|
4089
4177
|
studioState.nodes = s.nodes.map(function(n){return {icon:n.icon,agent:n.agent,label:n.label,status:'done'};});
|
|
4090
4178
|
studioState.log = s.log;
|
|
4091
4179
|
studioState.result = s.result;
|
|
4180
|
+
studioState.canvas = s.canvas || null;
|
|
4092
4181
|
studioState.running = false;
|
|
4093
4182
|
var ta = document.getElementById('studioTaskInput');
|
|
4094
4183
|
if (ta) ta.value = s.task;
|
|
4095
4184
|
renderStudioNodes(); renderStudioLog(); renderStudioResult();
|
|
4185
|
+
// Restore canvas if present
|
|
4186
|
+
if (s.canvas) {
|
|
4187
|
+
var cf = document.getElementById('canvasFrame');
|
|
4188
|
+
var cp = document.getElementById('canvasPanel');
|
|
4189
|
+
if (cf) cf.srcdoc = s.canvas;
|
|
4190
|
+
if (cp) cp.classList.add('open');
|
|
4191
|
+
var ct = document.getElementById('canvasTitle');
|
|
4192
|
+
if (ct) ct.textContent = 'Studio Report';
|
|
4193
|
+
var scb = document.getElementById('studioCanvasBtn');
|
|
4194
|
+
if (scb) scb.style.display = '';
|
|
4195
|
+
// Also store in allCanvasData so canvas panel nav works
|
|
4196
|
+
var convId = activeConvId || 'studio';
|
|
4197
|
+
if (!allCanvasData[convId]) allCanvasData[convId] = {canvases:[], browsers:[]};
|
|
4198
|
+
allCanvasData[convId].canvases.push({html: s.canvas, title: s.task.slice(0,60), ts: s.ts});
|
|
4199
|
+
canvasIdx = allCanvasData[convId].canvases.length - 1;
|
|
4200
|
+
canvasMode = 'canvas';
|
|
4201
|
+
}
|
|
4096
4202
|
showToast('success', 'Session restored', s.task.slice(0, 60), 3000);
|
|
4097
4203
|
}
|
|
4098
4204
|
|
|
@@ -4152,7 +4258,7 @@ function runStudioStep(idx, node, task, context, stepDef, signal) {
|
|
|
4152
4258
|
// Inject attachment into first step only — pass PDF/image as dedicated fields,
|
|
4153
4259
|
// NOT as raw base64 in context (would cause 100k+ token overflow for any real PDF).
|
|
4154
4260
|
// Cap accumulated context to ~40KB to avoid token overflow — keep the most recent content
|
|
4155
|
-
var cappedContext = context && context.length >
|
|
4261
|
+
var cappedContext = context && context.length > 120000 ? context.slice(-120000) : context;
|
|
4156
4262
|
var bodyObj = {stepIdx: idx, agent: node.agent, task: task, context: cappedContext, stepDef: stepDef};
|
|
4157
4263
|
if (idx === 0 && studioState.attachmentContext) {
|
|
4158
4264
|
var ac = studioState.attachmentContext;
|
|
@@ -4395,6 +4501,7 @@ function renderStudio(el) {
|
|
|
4395
4501
|
'<button id="studioCanvasBtn" onclick="openCanvasPanel()" title="' + t('canvas_open') + '" style="font-size:12px;padding:5px 14px;background:none;border:1px solid var(--border);border-radius:6px;color:var(--dim);cursor:pointer;font-weight:700;transition:all .2s">■ Canvas</button>' +
|
|
4396
4502
|
'</div>' +
|
|
4397
4503
|
'<div class="studio-canvas" id="studioNodes"></div>' +
|
|
4504
|
+
'<div id="studioParliamentBlock" style="display:none"></div>' +
|
|
4398
4505
|
'<div class="studio-log" id="studioLog" style="display:none"></div>' +
|
|
4399
4506
|
'<div id="studioResult"></div>' +
|
|
4400
4507
|
'<div id="studioSessionsBar" style="margin-top:16px;display:none"></div>' +
|
|
@@ -4940,6 +5047,24 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
4940
5047
|
.studio-arrow{display:flex;align-items:center;color:var(--border2);font-size:18px;padding:0 8px;flex-shrink:0;margin-bottom:30px;transition:color .4s}
|
|
4941
5048
|
.studio-arrow--active{color:var(--green3);animation:stFlow .5s ease-in-out infinite alternate}
|
|
4942
5049
|
.studio-arrow--done{color:#22c55e}
|
|
5050
|
+
.studio-parliament{background:linear-gradient(135deg,#0e0e1c 0%,#12122a 100%);border:1.5px solid #6366f1;border-radius:12px;padding:18px 20px;margin-bottom:16px;animation:stNodeIn .4s ease forwards}
|
|
5051
|
+
.studio-parliament__header{display:flex;align-items:center;gap:10px;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid #6366f133}
|
|
5052
|
+
.studio-parliament__master{display:flex;align-items:center;gap:8px;background:linear-gradient(90deg,#4f46e5,#7c3aed);border-radius:8px;padding:7px 12px;font-size:11px;font-weight:700;color:#fff;letter-spacing:.5px}
|
|
5053
|
+
.studio-parliament__master-icon{font-size:18px}
|
|
5054
|
+
.studio-parliament__title{font-size:10px;color:#a5b4fc;text-transform:uppercase;letter-spacing:1.2px;font-weight:700;margin-left:auto}
|
|
5055
|
+
.studio-parliament__round{font-size:10px;color:#6366f1;background:rgba(99,102,241,.12);border-radius:20px;padding:3px 10px;font-weight:700;animation:stPulse .9s ease-in-out infinite}
|
|
5056
|
+
.studio-parliament__agents{display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap;padding:4px 0}
|
|
5057
|
+
.studio-parliament__agent{display:flex;flex-direction:column;align-items:center;gap:5px;min-width:80px}
|
|
5058
|
+
.studio-parliament__agent-circle{width:44px;height:44px;border-radius:10px;border:1.5px solid #6366f1;background:#1a1a2e;display:flex;align-items:center;justify-content:center;font-size:18px;transition:all .3s}
|
|
5059
|
+
.studio-parliament__agent-circle--reading{border-color:#22d3ee;box-shadow:0 0 0 6px rgba(34,211,238,.15),0 0 16px rgba(34,211,238,.2);animation:stRing 1.4s ease-out infinite}
|
|
5060
|
+
.studio-parliament__agent-circle--done{border-color:#22c55e;background:rgba(34,197,94,.08)}
|
|
5061
|
+
.studio-parliament__agent-label{font-size:9px;color:#a5b4fc;text-align:center;font-weight:600;max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
5062
|
+
.studio-parliament__conn{display:flex;flex-direction:column;align-items:center;gap:2px;margin-bottom:16px}
|
|
5063
|
+
.studio-parliament__conn-line{width:2px;height:18px;background:linear-gradient(180deg,#6366f1,#22d3ee);border-radius:2px;animation:stFlow .7s ease-in-out infinite alternate}
|
|
5064
|
+
.studio-parliament__bidir{color:#6366f1;font-size:14px;animation:stPulse .6s ease-in-out infinite}
|
|
5065
|
+
.studio-parliament__reading{font-size:9px;color:#22d3ee;text-align:center;margin-top:6px;font-family:var(--mono);background:rgba(34,211,238,.07);border-radius:6px;padding:3px 8px}
|
|
5066
|
+
.studio-parliament__convergence{text-align:center;margin-top:12px;padding:8px;background:rgba(34,197,94,.07);border:1px solid rgba(34,197,94,.2);border-radius:8px;font-size:11px;color:#22c55e;font-weight:700}
|
|
5067
|
+
@keyframes stOrbit{0%{transform:translateX(0) scale(1)}50%{transform:translateX(4px) scale(1.04)}100%{transform:translateX(0) scale(1)}}
|
|
4943
5068
|
.studio-log{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:16px;max-height:380px;overflow-y:auto;font-size:11.5px;line-height:1.65}
|
|
4944
5069
|
.studio-log-entry{margin-bottom:12px;padding:10px 12px;border-radius:8px;background:var(--bg3);border:1px solid var(--border)}
|
|
4945
5070
|
.studio-log-entry:last-child{margin-bottom:0}
|