nothumanallowed 13.5.4 → 13.5.6
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 +2 -0
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +369 -146
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.6",
|
|
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
|
@@ -3529,6 +3529,7 @@ ${context ? `## OUTPUT FROM PREVIOUS AGENTS (use only what is RELEVANT to the wo
|
|
|
3529
3529
|
} else if (useStructuredGen) {
|
|
3530
3530
|
// ── Structured Generation ─────────────────────────────────
|
|
3531
3531
|
// Phase 1: ask for ONLY the section outline (headings list), fast and cheap
|
|
3532
|
+
sendToken('[Pianificazione struttura report...] ');
|
|
3532
3533
|
const structConfig = Object.assign({}, config, { thinking: 'off' });
|
|
3533
3534
|
const outlineSys = `You are ${agent}, a specialist AI agent. Today is ${today}. Respond in ${language}.
|
|
3534
3535
|
Your task: plan the sections of a complete structured report for this goal: ${task}
|
|
@@ -3591,6 +3592,7 @@ ${dataBlock}
|
|
|
3591
3592
|
${writtenSoFar ? `## REPORT WRITTEN SO FAR (for consistency):\n${writtenSoFar.slice(-3000)}` : ''}`;
|
|
3592
3593
|
const secUser = `Write the complete body content for this section (do NOT repeat the heading):\n${heading}`;
|
|
3593
3594
|
sendToken('\n\n' + heading + '\n');
|
|
3595
|
+
sendToken('[Sezione ' + (si + 1) + ' di ' + headingLines.length + '...] ');
|
|
3594
3596
|
let secContent = '';
|
|
3595
3597
|
try {
|
|
3596
3598
|
secContent = await streamCall(secSys, secUser, { max_tokens: 2000, thinking: 'off' }, 60000, sendToken);
|
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.
|
|
8
|
+
export const VERSION = '13.5.6';
|
|
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
|
@@ -3405,7 +3405,20 @@ function studioLog(agent, icon, text, type, update) {
|
|
|
3405
3405
|
var time = new Date().toLocaleTimeString('en', {hour:'2-digit', minute:'2-digit', second:'2-digit', hour12:false});
|
|
3406
3406
|
if (update && studioState.log.length) {
|
|
3407
3407
|
var last = studioState.log[studioState.log.length - 1];
|
|
3408
|
-
if (last.agent === agent) {
|
|
3408
|
+
if (last.agent === agent) {
|
|
3409
|
+
last.text = text; last.type = type || last.type;
|
|
3410
|
+
// Streaming finished: remove data-rlen from the DOM entry so renderStudioLog re-renders it as markdown
|
|
3411
|
+
var logEl = document.getElementById('studioLog');
|
|
3412
|
+
if (logEl) {
|
|
3413
|
+
var entries = logEl.querySelectorAll('.studio-log-entry');
|
|
3414
|
+
var lastEntry = entries[entries.length - 1];
|
|
3415
|
+
if (lastEntry) {
|
|
3416
|
+
var tb2 = lastEntry.querySelector('.studio-log-entry__text');
|
|
3417
|
+
if (tb2) tb2.removeAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110));
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
3420
|
+
renderStudioLog(); return;
|
|
3421
|
+
}
|
|
3409
3422
|
}
|
|
3410
3423
|
studioState.log.push({agent: agent, icon: icon, text: text, time: time, type: type||'agent'});
|
|
3411
3424
|
renderStudioLog();
|
|
@@ -3607,6 +3620,205 @@ function officeRoomDecor() {
|
|
|
3607
3620
|
\x27<div class="prl-office-plant2">\x27+plant2Svg+\x27</div>\x27;
|
|
3608
3621
|
}
|
|
3609
3622
|
|
|
3623
|
+
// ── Isometric JRPG-style scene renderer ────────────────────────────────────
|
|
3624
|
+
// Projects grid positions onto an isometric plane.
|
|
3625
|
+
// iso(col, row) → {x, y} pixel coordinates in the scene container.
|
|
3626
|
+
// Characters are positioned with position:absolute, scale by row for depth.
|
|
3627
|
+
var ISO_TILE_W = 72;
|
|
3628
|
+
var ISO_TILE_H = 36;
|
|
3629
|
+
var ISO_ORIGIN_X = 260; // center-left of scene
|
|
3630
|
+
var ISO_ORIGIN_Y = 40; // top of scene
|
|
3631
|
+
function isoProject(col, row) {
|
|
3632
|
+
return {
|
|
3633
|
+
x: ISO_ORIGIN_X + (col - row) * (ISO_TILE_W / 2),
|
|
3634
|
+
y: ISO_ORIGIN_Y + (col + row) * (ISO_TILE_H / 2)
|
|
3635
|
+
};
|
|
3636
|
+
}
|
|
3637
|
+
// Draw isometric floor tiles as SVG
|
|
3638
|
+
function isoFloorSvg(cols, rows) {
|
|
3639
|
+
var w = 600; var h = 240;
|
|
3640
|
+
var out = \x27<svg viewBox="0 0 \x27+w+\x27 \x27+h+\x27" width="\x27+w+\x27" height="\x27+h+\x27" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:0;left:0;pointer-events:none;z-index:0">\x27;
|
|
3641
|
+
// Back wall — two side walls
|
|
3642
|
+
out += \x27<polygon points="0,80 300,20 300,100 0,160" fill="#1a1535" opacity=".7"/>\x27;
|
|
3643
|
+
out += \x27<polygon points="300,20 600,80 600,160 300,100" fill="#141030" opacity=".7"/>\x27;
|
|
3644
|
+
// Wall top edge
|
|
3645
|
+
out += \x27<line x1="0" y1="80" x2="300" y2="20" stroke="#3a3060" stroke-width="1.5"/>\x27;
|
|
3646
|
+
out += \x27<line x1="300" y1="20" x2="600" y2="80" stroke="#3a3060" stroke-width="1.5"/>\x27;
|
|
3647
|
+
// Wall window left
|
|
3648
|
+
out += \x27<polygon points="60,82 130,62 130,102 60,122" fill="#1a2840" stroke="#2a4060" stroke-width="1"/>\x27;
|
|
3649
|
+
out += \x27<polygon points="65,85 125,66 125,98 65,117" fill="#7ecfff" opacity=".15" stroke="#4a90c0" stroke-width=".5"/>\x27;
|
|
3650
|
+
// Wall window right
|
|
3651
|
+
out += \x27<polygon points="470,82 540,62 540,102 470,122" fill="#1a2840" stroke="#2a4060" stroke-width="1"/>\x27;
|
|
3652
|
+
out += \x27<polygon points="475,85 535,66 535,98 475,117" fill="#7ecfff" opacity=".15" stroke="#4a90c0" stroke-width=".5"/>\x27;
|
|
3653
|
+
// Sunlight shafts
|
|
3654
|
+
out += \x27<polygon points="80,102 120,90 125,160 85,175" fill="rgba(200,230,255,.04)"/>\x27;
|
|
3655
|
+
out += \x27<polygon points="490,90 530,102 535,175 495,160" fill="rgba(200,230,255,.04)"/>\x27;
|
|
3656
|
+
// Ceiling lamp
|
|
3657
|
+
out += \x27<ellipse cx="300" cy="22" rx="20" ry="6" fill="#2a2050" stroke="#4a3080" stroke-width="1"/>\x27;
|
|
3658
|
+
out += \x27<ellipse cx="300" cy="24" rx="18" ry="10" fill="rgba(255,220,100,.12)"/>\x27;
|
|
3659
|
+
out += \x27<line x1="300" y1="0" x2="300" y2="22" stroke="#3a3060" stroke-width="1.5"/>\x27;
|
|
3660
|
+
// Floor tiles — iso grid
|
|
3661
|
+
for (var r = 0; r < rows; r++) {
|
|
3662
|
+
for (var c = 0; c < cols; c++) {
|
|
3663
|
+
var p = isoProject(c, r);
|
|
3664
|
+
var tx = p.x; var ty = p.y + 80;
|
|
3665
|
+
// Diamond tile
|
|
3666
|
+
var pts = (tx)+\x27,\x27+(ty) + \x27 \x27+(tx+ISO_TILE_W/2)+\x27,\x27+(ty+ISO_TILE_H/2) + \x27 \x27+tx+\x27,\x27+(ty+ISO_TILE_H) + \x27 \x27+(tx-ISO_TILE_W/2)+\x27,\x27+(ty+ISO_TILE_H/2);
|
|
3667
|
+
var tileEven = (r+c) % 2 === 0;
|
|
3668
|
+
out += \x27<polygon points="\x27+pts+\x27" fill="\x27+(tileEven?\x27#1e1840\x27:\x27#1a1535\x27)+\x27" stroke="#2a2050" stroke-width=".8"/>\x27;
|
|
3669
|
+
// Tile highlight (top-left edge)
|
|
3670
|
+
out += \x27<line x1="\x27+(tx-ISO_TILE_W/2)+\x27" y1="\x27+(ty+ISO_TILE_H/2)+\x27" x2="\x27+tx+\x27" y2="\x27+ty+\x27" stroke="rgba(255,255,255,.04)" stroke-width=".6"/>\x27;
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
out += \x27</svg>\x27;
|
|
3674
|
+
return out;
|
|
3675
|
+
}
|
|
3676
|
+
// Small isometric desk object at iso position
|
|
3677
|
+
function isoDeskSvg(x, y, accentColor) {
|
|
3678
|
+
var ac = accentColor || \x27#3a3060\x27;
|
|
3679
|
+
return \x27<svg viewBox="0 0 64 40" width="64" height="40" xmlns="http://www.w3.org/2000/svg" style="position:absolute;left:\x27+(x-32)+\x27px;top:\x27+(y+10)+\x27px;z-index:\x27+(Math.round(y))+\x27;pointer-events:none">\x27+
|
|
3680
|
+
// Desk top face
|
|
3681
|
+
\x27<polygon points="32,4 56,16 32,28 8,16" fill="#1e1840" stroke="\x27+ac+\x27" stroke-width="1.2"/>\x27+
|
|
3682
|
+
// Desk right face
|
|
3683
|
+
\x27<polygon points="56,16 56,32 32,44 32,28" fill="#120e28" stroke="\x27+ac+\x2788" stroke-width=".8"/>\x27+
|
|
3684
|
+
// Desk left face
|
|
3685
|
+
\x27<polygon points="8,16 32,28 32,44 8,32" fill="#161230" stroke="\x27+ac+\x2766" stroke-width=".8"/>\x27+
|
|
3686
|
+
// Monitor on desk
|
|
3687
|
+
\x27<polygon points="24,8 38,14 38,22 24,16" fill="\x27+(ac===\x27#22c55e\x27?\x27#0a2010\x27:\x27#0d0d1e\x27)+\x27" stroke="\x27+ac+\x27" stroke-width="1"/>\x27+
|
|
3688
|
+
\x27<polygon points="24,10 36,15 36,20 24,15" fill="\x27+(ac===\x27#22c55e\x27?\x27#0a2810\x27:\x27#111128\x27)+\x27"/>\x27+
|
|
3689
|
+
// Screen lines
|
|
3690
|
+
\x27<line x1="26" y1="12" x2="34" y2="15" stroke="\x27+ac+\x27" stroke-width=".8" opacity=".8"/>\x27+
|
|
3691
|
+
\x27<line x1="26" y1="14" x2="33" y2="17" stroke="\x27+ac+\x27" stroke-width=".8" opacity=".5"/>\x27+
|
|
3692
|
+
\x27<line x1="26" y1="16" x2="32" y2="18" stroke="\x27+ac+\x27" stroke-width=".8" opacity=".3"/>\x27+
|
|
3693
|
+
\x27</svg>\x27;
|
|
3694
|
+
}
|
|
3695
|
+
// Isometric JRPG sprite character — top-down 3/4 perspective, Pokemon-style
|
|
3696
|
+
function isoCharSvg(opts) {
|
|
3697
|
+
var skin = opts.skin || \x27#fbbf24\x27;
|
|
3698
|
+
var shirt = opts.shirt || \x27#4f46e5\x27;
|
|
3699
|
+
var hair = opts.hair || \x27#1a0e08\x27;
|
|
3700
|
+
var isActive = opts.isActive;
|
|
3701
|
+
var isDone = opts.isDone;
|
|
3702
|
+
var scale = opts.scale || 1;
|
|
3703
|
+
var glow = isActive ? (\x27filter:drop-shadow(0 0 6px \x27+(opts.accentColor||shirt)+\x27)\x27) : (isDone ? \x27filter:drop-shadow(0 0 4px #22c55e44)\x27 : \x27\x27);
|
|
3704
|
+
var armCls = isActive ? \x27class="prl-arm"\x27 : \x27\x27;
|
|
3705
|
+
var headCls = isActive ? \x27class="prl-head"\x27 : \x27\x27;
|
|
3706
|
+
var w = Math.round(48 * scale); var h = Math.round(64 * scale);
|
|
3707
|
+
return \x27<svg viewBox="0 0 48 64" width="\x27+w+\x27" height="\x27+h+\x27" xmlns="http://www.w3.org/2000/svg" style="\x27+glow+\x27;display:block;overflow:visible">\x27+
|
|
3708
|
+
// Shadow beneath character
|
|
3709
|
+
\x27<ellipse cx="24" cy="62" rx="\x27+(11*scale)+\x27" ry="\x27+(4*scale)+\x27" fill="rgba(0,0,0,.3)"/>\x27+
|
|
3710
|
+
// Legs
|
|
3711
|
+
\x27<path d="M18 42 C17 50 16 56 15 60 C14 62 17 63 19 62 C21 61 21 56 21 50 L21 42 Z" fill="\x27+shirt+\x27cc" class="prl-master-leg-l"/>\x27+
|
|
3712
|
+
\x27<path d="M24 42 C25 50 26 56 27 60 C28 62 25 63 23 62 C21 61 21 56 21 50 L21 42 Z" fill="\x27+shirt+\x27cc" class="prl-master-leg-r"/>\x27+
|
|
3713
|
+
// Shoes
|
|
3714
|
+
\x27<ellipse cx="16" cy="62" rx="4" ry="2" fill="#1a0e04" transform="rotate(-10 16 62)"/>\x27+
|
|
3715
|
+
\x27<ellipse cx="26" cy="62" rx="4" ry="2" fill="#1a0e04" transform="rotate(10 26 62)"/>\x27+
|
|
3716
|
+
// Body
|
|
3717
|
+
\x27<rect x="13" y="26" width="20" height="18" rx="3" fill="\x27+shirt+\x27"/>\x27+
|
|
3718
|
+
\x27<rect x="13" y="26" width="10" height="18" rx="3" fill="rgba(0,0,0,.1)"/>\x27+
|
|
3719
|
+
// Collar
|
|
3720
|
+
\x27<path d="M21 26 L18 30 L21 28 L24 30 Z" fill="\x27+skin+\x27"/>\x27+
|
|
3721
|
+
// Arms
|
|
3722
|
+
\x27<g \x27+armCls+\x27>\x27+
|
|
3723
|
+
\x27<path d="M13 28 C8 30 6 35 6 39 C6 42 9 43 11 42 C13 41 13 37 14 33 Z" fill="\x27+shirt+\x27"/>\x27+
|
|
3724
|
+
\x27<ellipse cx="7" cy="41" rx="4" ry="3" fill="\x27+skin+\x27" transform="rotate(-15 7 41)"/>\x27+
|
|
3725
|
+
\x27<path d="M33 28 C38 30 40 35 40 39 C40 42 37 43 35 42 C33 41 33 37 32 33 Z" fill="\x27+shirt+\x27"/>\x27+
|
|
3726
|
+
\x27<ellipse cx="39" cy="41" rx="4" ry="3" fill="\x27+skin+\x27" transform="rotate(15 39 41)"/>\x27+
|
|
3727
|
+
\x27</g>\x27+
|
|
3728
|
+
// Head
|
|
3729
|
+
\x27<g \x27+headCls+\x27>\x27+
|
|
3730
|
+
\x27<ellipse cx="21" cy="13" rx="11" ry="12" fill="\x27+skin+\x27"/>\x27+
|
|
3731
|
+
\x27<path d="M10 13 C10 6 14 1 21 0 C28 1 32 6 32 13 C31 7 28 4 21 3 C14 4 11 7 10 13" fill="\x27+hair+\x27"/>\x27+
|
|
3732
|
+
\x27<circle cx="16" cy="14" r="1.5" fill="#0a0a14"/>\x27+
|
|
3733
|
+
\x27<circle cx="26" cy="14" r="1.5" fill="#0a0a14"/>\x27+
|
|
3734
|
+
\x27<circle cx="16.7" cy="13" r=".7" fill="rgba(255,255,255,.9)"/>\x27+
|
|
3735
|
+
(isDone ?
|
|
3736
|
+
\x27<path d="M15 20 Q21 24 27 20" stroke="#8b4513" stroke-width="1.5" fill="none" stroke-linecap="round"/>\x27+
|
|
3737
|
+
\x27<path d="M16 20.5 Q21 23 26 20.5 Q21 22 16 20.5" fill="#fff" opacity=".6"/>\x27
|
|
3738
|
+
: isActive ?
|
|
3739
|
+
\x27<path d="M15 19 Q21 21 27 19" stroke="#8b4513" stroke-width="1.4" fill="none" stroke-linecap="round"/>\x27
|
|
3740
|
+
:
|
|
3741
|
+
\x27<path d="M16 20 Q21 22 26 20" stroke="#8b4513" stroke-width="1.2" fill="none" stroke-linecap="round"/>\x27
|
|
3742
|
+
)+
|
|
3743
|
+
\x27</g>\x27+
|
|
3744
|
+
\x27</svg>\x27;
|
|
3745
|
+
}
|
|
3746
|
+
// Orchestrator — bigger, crowned, JRPG boss sprite
|
|
3747
|
+
function isoOrchSvg(hasActive, doneRatio) {
|
|
3748
|
+
var mc = \x27#818cf8\x27;
|
|
3749
|
+
var armCls = hasActive ? \x27class="prl-master-arm-l"\x27 : \x27\x27;
|
|
3750
|
+
var armRCls = hasActive ? \x27class="prl-master-arm-r"\x27 : \x27\x27;
|
|
3751
|
+
return \x27<svg viewBox="0 0 60 80" width="58" height="76" xmlns="http://www.w3.org/2000/svg" style="display:block;overflow:visible;filter:drop-shadow(0 0 10px \x27+mc+\x27aa)">\x27+
|
|
3752
|
+
// Shadow
|
|
3753
|
+
\x27<ellipse cx="30" cy="78" rx="16" ry="5" fill="rgba(0,0,0,.4)"/>\x27+
|
|
3754
|
+
// Legs
|
|
3755
|
+
\x27<path d="M24 52 C23 60 22 67 21 72 C20 75 22 76 24 76 C26 76 27 74 27 71 C28 65 28 58 28 52 Z" fill="#1e1c4a" class="prl-master-leg-l"/>\x27+
|
|
3756
|
+
\x27<path d="M30 52 C31 60 32 67 33 72 C34 75 32 76 30 76 C28 76 27 74 27 71 C26 65 26 58 26 52 Z" fill="#1e1c4a" class="prl-master-leg-r"/>\x27+
|
|
3757
|
+
// Shoes
|
|
3758
|
+
\x27<ellipse cx="20" cy="74" rx="5" ry="2.5" fill="#0a0a14" transform="rotate(-8 20 74)"/>\x27+
|
|
3759
|
+
\x27<ellipse cx="34" cy="74" rx="5" ry="2.5" fill="#0a0a14" transform="rotate(8 34 74)"/>\x27+
|
|
3760
|
+
// Suit body
|
|
3761
|
+
\x27<path d="M14 32 C13 30 16 27 27 25 C38 27 41 30 40 32 L41 52 L13 52 Z" fill="#252464"/>\x27+
|
|
3762
|
+
\x27<path d="M14 32 C13 30 16 27 27 25 L27 52 L13 52 Z" fill="#1e1d52"/>\x27+
|
|
3763
|
+
\x27<path d="M27 25 C38 27 41 30 40 32 L41 52 L27 52 Z" fill="#2a2870"/>\x27+
|
|
3764
|
+
// Lapels
|
|
3765
|
+
\x27<path d="M27 25 L21 33 L24 36 L27 29 Z" fill="#1a1940"/>\x27+
|
|
3766
|
+
\x27<path d="M27 25 L33 33 L30 36 L27 29 Z" fill="#1a1940"/>\x27+
|
|
3767
|
+
\x27<path d="M27 29 L24 36 L27 34 L30 36 Z" fill="#f0f0fa"/>\x27+
|
|
3768
|
+
// Tie
|
|
3769
|
+
\x27<path d="M27 33 L26 44 L27 48 L28 44 Z" fill="\x27+mc+\x27"/>\x27+
|
|
3770
|
+
// Arms
|
|
3771
|
+
\x27<g \x27+armCls+\x27 style="transform-origin:14px 35px">\x27+
|
|
3772
|
+
\x27<path d="M14 35 C8 38 5 44 5 48 C5 51 8 52 10 51 C12 50 13 46 14 42 C15 39 14 36 14 35" fill="#252450"/>\x27+
|
|
3773
|
+
\x27<ellipse cx="6" cy="51" rx="5" ry="3.5" fill="#d4a97a" transform="rotate(-15 6 51)"/>\x27+
|
|
3774
|
+
\x27</g>\x27+
|
|
3775
|
+
\x27<g \x27+armRCls+\x27 style="transform-origin:40px 35px">\x27+
|
|
3776
|
+
\x27<path d="M40 35 C46 38 49 43 49 47 C49 50 46 51 44 50 C42 49 41 45 40 41 C39 38 40 36 40 35" fill="#252450"/>\x27+
|
|
3777
|
+
// Clipboard
|
|
3778
|
+
\x27<rect x="46" y="30" width="12" height="16" rx="2" fill="#1a1a2e" stroke="\x27+mc+\x2799" stroke-width="1.2"/>\x27+
|
|
3779
|
+
\x27<rect x="49" y="28" width="6" height="4" rx="1" fill="\x27+mc+\x27"/>\x27+
|
|
3780
|
+
\x27<line x1="48" y1="34" x2="56" y2="34" stroke="\x27+mc+\x27cc" stroke-width=".9"/>\x27+
|
|
3781
|
+
\x27<line x1="48" y1="37" x2="56" y2="37" stroke="\x27+mc+\x27aa" stroke-width=".9"/>\x27+
|
|
3782
|
+
\x27<line x1="48" y1="40" x2="54" y2="40" stroke="\x27+mc+\x2788" stroke-width=".9"/>\x27+
|
|
3783
|
+
\x27</g>\x27+
|
|
3784
|
+
// Neck
|
|
3785
|
+
\x27<rect x="24" y="25" width="6" height="5" rx="2" fill="#d4a97a"/>\x27+
|
|
3786
|
+
// Head
|
|
3787
|
+
\x27<ellipse cx="27" cy="14" rx="13" ry="13" fill="#d4a97a"/>\x27+
|
|
3788
|
+
\x27<path d="M14 14 C14 20 18 24 27 25 C36 24 40 20 40 14" fill="#d4a97a"/>\x27+
|
|
3789
|
+
// Hair
|
|
3790
|
+
\x27<path d="M14 14 C13 7 17 2 27 1 C37 2 41 7 40 14 C39 7 35 4 27 3 C19 4 15 7 14 14" fill="#1a0e08"/>\x27+
|
|
3791
|
+
// Eyes
|
|
3792
|
+
\x27<ellipse cx="22" cy="15" rx="3" ry="3.5" fill="#fff"/>\x27+
|
|
3793
|
+
\x27<ellipse cx="32" cy="15" rx="3" ry="3.5" fill="#fff"/>\x27+
|
|
3794
|
+
\x27<circle cx="22" cy="15.5" r="2" fill="#1e3a6e"/>\x27+
|
|
3795
|
+
\x27<circle cx="32" cy="15.5" r="2" fill="#1e3a6e"/>\x27+
|
|
3796
|
+
\x27<circle cx="22" cy="15.5" r="1.2" fill="#0a0a18"/>\x27+
|
|
3797
|
+
\x27<circle cx="32" cy="15.5" r="1.2" fill="#0a0a18"/>\x27+
|
|
3798
|
+
\x27<circle cx="23" cy="14" r=".8" fill="rgba(255,255,255,.9)"/>\x27+
|
|
3799
|
+
(hasActive ?
|
|
3800
|
+
\x27<path d="M21 21 Q27 25 33 21" stroke="#8b4513" stroke-width="1.8" fill="none" stroke-linecap="round"/>\x27+
|
|
3801
|
+
\x27<ellipse cx="27" cy="22.5" rx="3.5" ry="2" fill="#5a1a0a" opacity=".6"/>\x27
|
|
3802
|
+
:
|
|
3803
|
+
\x27<path d="M21 22 Q27 25 33 22" stroke="#8b4513" stroke-width="1.6" fill="none" stroke-linecap="round"/>\x27
|
|
3804
|
+
)+
|
|
3805
|
+
// Crown
|
|
3806
|
+
\x27<path d="M17 4 L20 9 L27 6 L34 9 L37 4 L27 1 Z" fill="#f59e0b"/>\x27+
|
|
3807
|
+
\x27<circle cx="20" cy="9" r="2" fill="#fbbf24"/>\x27+
|
|
3808
|
+
\x27<circle cx="27" cy="6" r="2" fill="#fbbf24"/>\x27+
|
|
3809
|
+
\x27<circle cx="34" cy="9" r="2" fill="#fbbf24"/>\x27+
|
|
3810
|
+
\x27</svg>\x27;
|
|
3811
|
+
}
|
|
3812
|
+
|
|
3813
|
+
// Skin/shirt/hair palette per agent label
|
|
3814
|
+
function agentPalette(lbl) {
|
|
3815
|
+
var skins = [\x27#fbbf24\x27,\x27#f97316\x27,\x27#e8c99a\x27,\x27#c8a97a\x27,\x27#d4a97a\x27,\x27#f5c07a\x27];
|
|
3816
|
+
var shirts = [\x27#4f46e5\x27,\x27#0891b2\x27,\x27#7c3aed\x27,\x27#059669\x27,\x27#dc2626\x27,\x27#d97706\x27];
|
|
3817
|
+
var hairs = [\x27#1a0e08\x27,\x27#4a3728\x27,\x27#c4a35a\x27,\x27#8b0000\x27,\x27#2c4a7c\x27,\x27#3d2b1f\x27];
|
|
3818
|
+
var i = Math.abs((lbl.charCodeAt(0)||65) + (lbl.charCodeAt(lbl.length-1)||90)) % 6;
|
|
3819
|
+
return {skin: skins[i], shirt: shirts[i], hair: hairs[i]};
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3610
3822
|
function renderStudioNodes() {
|
|
3611
3823
|
var el = document.getElementById('studioNodes');
|
|
3612
3824
|
if (!el) return;
|
|
@@ -3614,138 +3826,94 @@ function renderStudioNodes() {
|
|
|
3614
3826
|
el.innerHTML = '<div class="studio-canvas__empty"><div class="studio-canvas__empty-icon">⚙</div><div>Describe a task and click Run</div></div>';
|
|
3615
3827
|
return;
|
|
3616
3828
|
}
|
|
3617
|
-
// ── Parliament-style office scene ──────────────────────────────────────────
|
|
3618
|
-
// Renders all pipeline nodes as the same parliament office scene:
|
|
3619
|
-
// agents at desks, orchestrator walking + sbraita (speech bubble yelling).
|
|
3620
|
-
var hasActive = studioState.nodes.some(function(n){ return n.status === \x27running\x27; });
|
|
3621
|
-
var hasDone = studioState.nodes.some(function(n){ return n.status === \x27done\x27; });
|
|
3622
|
-
var showMaster = hasActive || hasDone;
|
|
3623
|
-
|
|
3624
|
-
// Sbraita phrases — orchestrator yells at agents
|
|
3625
|
-
var sbraitaPhrases = [
|
|
3626
|
-
\x27PIU VELOCE!!!\x27, \x27FOCUS!!!\x27, \x27DEADLINE!!!\x27, \x27CHE FAI??!\x27,
|
|
3627
|
-
\x27MUOVITI!!\x27, \x27NO ERRORI!\x27, \x27ADESSO!!\x27, \x27SBRIGATI!\x27
|
|
3628
|
-
];
|
|
3629
|
-
var activeNode = studioState.nodes.find(function(n){ return n.status === \x27running\x27; });
|
|
3630
|
-
var sbIdx = activeNode ? Math.abs((activeNode.label||activeNode.agent||\x27x\x27).charCodeAt(0)) % sbraitaPhrases.length : 0;
|
|
3631
|
-
var sbraitaText = sbraitaPhrases[sbIdx];
|
|
3632
3829
|
|
|
3633
|
-
|
|
3634
|
-
var
|
|
3635
|
-
|
|
3830
|
+
var nodes = studioState.nodes;
|
|
3831
|
+
var hasActive = nodes.some(function(n){ return n.status === \x27running\x27; });
|
|
3832
|
+
var doneCount = nodes.filter(function(n){ return n.status === \x27done\x27; }).length;
|
|
3833
|
+
var totalCount = nodes.length;
|
|
3834
|
+
var showMaster = hasActive || doneCount > 0;
|
|
3835
|
+
|
|
3836
|
+
// ── ISO scene dimensions ───────────────────────────────────────────────────
|
|
3837
|
+
var ISO_COLS = Math.max(nodes.length, 1);
|
|
3838
|
+
var SCENE_W = 600; var SCENE_H = 260;
|
|
3839
|
+
|
|
3840
|
+
// Distribute agents along row=1 of the iso grid, spaced evenly
|
|
3841
|
+
// Orchestrator walks on row=0 (further back = smaller)
|
|
3842
|
+
var agentsHtml = \x27\x27;
|
|
3843
|
+
nodes.forEach(function(n, idx) {
|
|
3636
3844
|
var isActive = n.status === \x27running\x27;
|
|
3637
3845
|
var isDone = n.status === \x27done\x27;
|
|
3638
3846
|
var isErr = n.status === \x27error\x27;
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3847
|
+
var lbl = n.label || n.agent;
|
|
3848
|
+
var pal = agentPalette(lbl);
|
|
3849
|
+
var accentColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : (isErr ? \x27#ef4444\x27 : \x27#3a3060\x27));
|
|
3850
|
+
|
|
3851
|
+
// Iso position: spread across columns, agents sit at row=2 (front row)
|
|
3852
|
+
var col = (idx + 0.5) * (ISO_COLS > 1 ? (ISO_COLS - 1) / ISO_COLS : 1) + 0.5;
|
|
3853
|
+
col = (idx * (ISO_COLS <= 1 ? 2 : (4 / ISO_COLS))) + 1;
|
|
3854
|
+
var row = 2.5;
|
|
3855
|
+
var pos = isoProject(col, row);
|
|
3856
|
+
var px = pos.x; var py = pos.y + 40;
|
|
3857
|
+
// scale: row 2.5 = 1.0, background rows smaller
|
|
3858
|
+
var charScale = 0.9 + row * 0.08;
|
|
3859
|
+
var zIdx = Math.round(py + 100);
|
|
3860
|
+
|
|
3861
|
+
// Speech bubble content
|
|
3862
|
+
var bubbleText = \x27\x27;
|
|
3863
|
+
var bubbleColor = \x27#6366f1\x27;
|
|
3864
|
+
if (isActive) { bubbleText = \x27...lavora\x27; bubbleColor = \x27#6366f1\x27; }
|
|
3865
|
+
else if (isDone) { bubbleText = \x27\u2714 fatto\x27; bubbleColor = \x27#22c55e\x27; }
|
|
3866
|
+
else if (isErr) { bubbleText = \x27\u2715 errore\x27; bubbleColor = \x27#ef4444\x27; }
|
|
3867
|
+
else { bubbleText = \x27in attesa\x27; bubbleColor = \x27#4a4a6a\x27; }
|
|
3868
|
+
|
|
3869
|
+
var charSvg = isoCharSvg({skin: pal.skin, shirt: pal.shirt, hair: pal.hair,
|
|
3870
|
+
isActive: isActive, isDone: isDone, scale: charScale, accentColor: accentColor});
|
|
3871
|
+
|
|
3872
|
+
var charW = Math.round(48 * charScale);
|
|
3873
|
+
var charH = Math.round(64 * charScale);
|
|
3874
|
+
|
|
3875
|
+
agentsHtml += \x27<div class="iso-agent" data-agent-label="\x27+esc(lbl)+\x27" style="position:absolute;left:\x27+(px - charW/2)+\x27px;top:\x27+(py - charH)+\x27px;z-index:\x27+zIdx+\x27;display:flex;flex-direction:column;align-items:center;gap:2px;cursor:pointer" onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))">\x27;
|
|
3876
|
+
// Thought bubble above head
|
|
3877
|
+
agentsHtml += \x27<div class="iso-bubble\x27+(isActive?\x27 iso-bubble--active\x27:\x27\x27)+\x27" id="isobubble_\x27+idx+\x27" style="border-color:\x27+bubbleColor+\x27;color:\x27+bubbleColor+\x27">\x27+esc(bubbleText)+\x27</div>\x27;
|
|
3878
|
+
agentsHtml += charSvg;
|
|
3879
|
+
// Name tag
|
|
3880
|
+
agentsHtml += \x27<div class="iso-name" style="color:\x27+(isDone?\x27#4ade80\x27:(isActive?\x27#a5b4fc\x27:(isErr?\x27#f87171\x27:\x27#6b7280\x27)))+\x27">\x27+esc(lbl)+\x27</div>\x27;
|
|
3881
|
+
// Iso desk below character
|
|
3882
|
+
agentsHtml += isoDeskSvg(px, py - charH/2, accentColor);
|
|
3883
|
+
agentsHtml += \x27</div>\x27;
|
|
3648
3884
|
});
|
|
3649
3885
|
|
|
3650
|
-
// ──
|
|
3651
|
-
var
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
\x27<
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
\x27<circle cx="25" cy="42" r="1.2" fill="\x27+masterColor3+\x27aa"/>\x27+
|
|
3667
|
-
\x27<circle cx="20" cy="36" r="2.5" fill="#0d0d1e" stroke="\x27+masterColor3+\x2799" stroke-width="1"/>\x27+
|
|
3668
|
-
\x27<text x="20" y="39.5" text-anchor="middle" font-size="4" fill="\x27+masterColor3+\x27" font-family="system-ui,sans-serif">N</text>\x27+
|
|
3669
|
-
\x27<g class="prl-master-arm-l">\x27+
|
|
3670
|
-
\x27<path d="M13 34 C8 37 6 42 6 46 C6 49 9 50 11 49 C13 48 13 45 14 41 C15 38 14 35 13 34" fill="#252450"/>\x27+
|
|
3671
|
-
\x27<path d="M6 46 C4 48 4 51 5 53 C6 55 9 55 10 53 C11 51 10 48 10 46 Z" fill="#d4a97a"/>\x27+
|
|
3672
|
-
\x27<ellipse cx="7" cy="54" rx="4.5" ry="3.5" fill="#d4a97a" transform="rotate(-15 7 54)"/>\x27+
|
|
3673
|
-
\x27</g>\x27+
|
|
3674
|
-
\x27<g class="prl-master-arm-r">\x27+
|
|
3675
|
-
\x27<path d="M37 34 C42 37 44 41 44 45 C44 48 41 49 39 48 C37 47 37 44 37 40 C37 37 37 35 37 34" fill="#252450"/>\x27+
|
|
3676
|
-
\x27<path d="M44 44 C46 46 47 49 46 52 C45 54 42 54 41 52 C40 50 41 47 41 45 Z" fill="#d4a97a"/>\x27+
|
|
3677
|
-
\x27<ellipse cx="45" cy="52" rx="4" ry="3" fill="#d4a97a" transform="rotate(15 45 52)"/>\x27+
|
|
3678
|
-
\x27<rect x="43" y="32" width="14" height="19" rx="2.5" fill="#1a1a2e" stroke="\x27+masterColor3+\x2799" stroke-width="1.5"/>\x27+
|
|
3679
|
-
\x27<rect x="47" y="30" width="6" height="5" rx="1.5" fill="\x27+masterColor3+\x27"/>\x27+
|
|
3680
|
-
\x27<rect x="48" y="31" width="4" height="3" rx="1" fill="#0f0f1e"/>\x27+
|
|
3681
|
-
\x27<line x1="46" y1="36" x2="54" y2="36" stroke="\x27+masterColor3+\x27cc" stroke-width="1"/>\x27+
|
|
3682
|
-
\x27<line x1="46" y1="39" x2="54" y2="39" stroke="\x27+masterColor3+\x27aa" stroke-width="1"/>\x27+
|
|
3683
|
-
\x27<line x1="46" y1="42" x2="54" y2="42" stroke="\x27+masterColor3+\x2788" stroke-width="1"/>\x27+
|
|
3684
|
-
\x27</g>\x27+
|
|
3685
|
-
\x27<path d="M22 25 L28 25 L28 29 Q28 31 25 31 Q22 31 22 29 Z" fill="#d4a97a"/>\x27+
|
|
3686
|
-
\x27<ellipse cx="25" cy="15" rx="12" ry="13" fill="#d4a97a"/>\x27+
|
|
3687
|
-
\x27<path d="M14 15 C14 22 18 26 25 27 C32 26 36 22 36 15" fill="#d4a97a"/>\x27+
|
|
3688
|
-
\x27<path d="M13 13 C11 13 10 15 10 17 C10 19 11 20 13 20 C14 20 14.5 19 14 17 C14.5 15 14 13 13 13" fill="#d4a97a"/>\x27+
|
|
3689
|
-
\x27<path d="M37 13 C39 13 40 15 40 17 C40 19 39 20 37 20 C36 20 35.5 19 36 17 C35.5 15 36 13 37 13" fill="#d4a97a"/>\x27+
|
|
3690
|
-
\x27<path d="M13 14 C12 7 16 2 25 1 C34 2 38 7 37 14 C36 7 32 4 25 3 C18 4 14 7 13 14" fill="#1a0e08"/>\x27+
|
|
3691
|
-
\x27<path d="M22 3 C21 4 21 6 22 8" stroke="rgba(255,255,255,.15)" stroke-width="1.5" fill="none"/>\x27+
|
|
3692
|
-
\x27<path d="M16.5 11 Q19 9.5 21.5 11" stroke="#1a0e08" stroke-width="1.8" fill="none" stroke-linecap="round"/>\x27+
|
|
3693
|
-
\x27<path d="M28.5 11 Q31 9.5 33.5 11" stroke="#1a0e08" stroke-width="1.8" fill="none" stroke-linecap="round"/>\x27+
|
|
3694
|
-
\x27<ellipse cx="19.5" cy="14.5" rx="3.2" ry="3.5" fill="#fff"/>\x27+
|
|
3695
|
-
\x27<ellipse cx="30.5" cy="14.5" rx="3.2" ry="3.5" fill="#fff"/>\x27+
|
|
3696
|
-
\x27<circle cx="19.5" cy="15" r="2.3" fill="#1e3a6e"/>\x27+
|
|
3697
|
-
\x27<circle cx="30.5" cy="15" r="2.3" fill="#1e3a6e"/>\x27+
|
|
3698
|
-
\x27<circle cx="19.5" cy="15" r="1.3" fill="#0a0a18"/>\x27+
|
|
3699
|
-
\x27<circle cx="30.5" cy="15" r="1.3" fill="#0a0a18"/>\x27+
|
|
3700
|
-
\x27<circle cx="20.5" cy="13.7" r=".9" fill="rgba(255,255,255,.95)"/>\x27+
|
|
3701
|
-
\x27<circle cx="31.5" cy="13.7" r=".9" fill="rgba(255,255,255,.95)"/>\x27+
|
|
3702
|
-
// Angry expression when active (furrowed brows + open mouth)
|
|
3703
|
-
(hasActive ?
|
|
3704
|
-
\x27<path d="M19.5 23 Q25 26 30.5 23" stroke="#8b4513" stroke-width="1.8" fill="none" stroke-linecap="round"/>\x27+
|
|
3705
|
-
\x27<path d="M20 23.5 Q25 26 30 23.5 Q25 25 20 23.5" fill="#fff" opacity=".6"/>\x27+
|
|
3706
|
-
// Open mouth / yelling
|
|
3707
|
-
\x27<ellipse cx="25" cy="24.5" rx="3" ry="1.5" fill="#5a1a0a" opacity=".7"/>\x27
|
|
3708
|
-
:
|
|
3709
|
-
\x27<path d="M19.5 24 Q25 27.5 30.5 24" stroke="#8b4513" stroke-width="1.8" fill="none" stroke-linecap="round"/>\x27+
|
|
3710
|
-
\x27<path d="M20 24.5 Q25 27 30 24.5 Q25 26.5 20 24.5" fill="#fff" opacity=".7"/>\x27
|
|
3711
|
-
)+
|
|
3712
|
-
\x27<circle cx="25" cy="-4" r="9" fill="\x27+masterColor3+\x2722" stroke="\x27+masterColor3+\x2766" stroke-width="1.5"/>\x27+
|
|
3713
|
-
\x27<path d="M25 -13 L30 -4 L25 5 L20 -4 Z" fill="\x27+masterColor3+\x27" stroke="\x27+masterColor3+\x27cc" stroke-width=".8"/>\x27+
|
|
3714
|
-
\x27<path d="M25 -13 L30 -4 L25 -3 L20 -4 Z" fill="\x27+masterColor3+\x27aa"/>\x27+
|
|
3715
|
-
\x27</svg>\x27;
|
|
3886
|
+
// ── Orchestrator ──────────────────────────────────────────────────────────
|
|
3887
|
+
var orchHtml = \x27\x27;
|
|
3888
|
+
if (showMaster) {
|
|
3889
|
+
var oPh = isoProject(ISO_COLS / 2, 0.5);
|
|
3890
|
+
var orchPhrase = [\x27Analizzo il progresso...\x27, \x27Verifico gli step...\x27, \x27Coordinamento...\x27, \x27Supervisione in corso\x27][Math.floor(Date.now()/3000)%4];
|
|
3891
|
+
var orchDone = !hasActive && doneCount === totalCount;
|
|
3892
|
+
var orchAnim = hasActive ? \x27prl-master-walk\x27 : (orchDone ? \x27prl-master-done\x27 : \x27\x27);
|
|
3893
|
+
var orchStatus = hasActive
|
|
3894
|
+
? (\x27Eseguiti \x27+doneCount+\x27/\x27+totalCount)
|
|
3895
|
+
: (orchDone ? \x27Workflow completato!\x27 : \x27In pianificazione\x27);
|
|
3896
|
+
orchHtml = \x27<div class="prl-master \x27+orchAnim+\x27" id="wfOrch" style="position:absolute;left:\x27+(oPh.x+30)+\x27px;top:\x27+(oPh.y-10)+\x27px;z-index:50;display:flex;flex-direction:column;align-items:center;gap:2px">\x27+
|
|
3897
|
+
\x27<div class="iso-bubble iso-bubble--orch" id="wfOrchBubble" style="border-color:#818cf8;color:#a5b4fc;max-width:120px">\x27+esc(orchStatus)+\x27</div>\x27+
|
|
3898
|
+
isoOrchSvg(hasActive, doneCount / Math.max(totalCount,1))+
|
|
3899
|
+
\x27<div class="prl-master-label" style="color:#818cf8;font-size:8px">Orchestratore</div>\x27+
|
|
3900
|
+
\x27</div>\x27;
|
|
3901
|
+
}
|
|
3716
3902
|
|
|
3717
|
-
// Speech bubble "sbraita" when there is an active agent
|
|
3718
|
-
var bubbleHtml = showMaster && hasActive
|
|
3719
|
-
? (\x27<div class="wf-sbraita-bubble">\x27+sbraitaText+\x27</div>\x27)
|
|
3720
|
-
: \x27\x27;
|
|
3721
|
-
|
|
3722
|
-
// Phase label
|
|
3723
|
-
var doneCount = studioState.nodes.filter(function(n){return n.status===\x27done\x27;}).length;
|
|
3724
|
-
var totalCount = studioState.nodes.length;
|
|
3725
|
-
var wfMasterAnim = hasActive ? \x27prl-master-walk\x27 : (doneCount===totalCount && totalCount>0 ? \x27prl-master-done\x27 : \x27prl-master-walk\x27);
|
|
3726
|
-
var masterWfHtml = showMaster ? (
|
|
3727
|
-
\x27<div class="prl-master \x27+wfMasterAnim+\x27 wf-master" style="bottom:20px">\x27+
|
|
3728
|
-
bubbleHtml+
|
|
3729
|
-
masterSvg2+
|
|
3730
|
-
\x27<div class="prl-master-label" style="color:\x27+masterColor3+\x27;font-size:8px">Orchestratore</div>\x27+
|
|
3731
|
-
\x27</div>\x27
|
|
3732
|
-
) : \x27\x27;
|
|
3733
3903
|
var phaseLabel2 = hasActive
|
|
3734
|
-
? (\x27Workflow in esecuzione \u2014 \x27+doneCount+\x27/\x27+totalCount
|
|
3904
|
+
? (\x27Workflow in esecuzione \u2014 \x27+doneCount+\x27/\x27+totalCount)
|
|
3735
3905
|
: (doneCount===totalCount && totalCount>0 ? \x27Workflow completato\x27 : \x27Workflow pianificato\x27);
|
|
3736
3906
|
var phaseColor2 = hasActive ? \x27#6366f1\x27 : (doneCount===totalCount && totalCount>0 ? \x27#22c55e\x27 : \x27#6b7280\x27);
|
|
3737
3907
|
|
|
3738
|
-
|
|
3908
|
+
el.innerHTML =
|
|
3909
|
+
\x27<div class="prl-wrap" style="border-color:\x27+phaseColor2+\x2744;padding-bottom:8px">\x27+
|
|
3739
3910
|
\x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor2+\x27">\x27+phaseLabel2+\x27</span></div>\x27+
|
|
3740
|
-
\x27<div class="
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
masterWfHtml+
|
|
3911
|
+
\x27<div class="iso-scene" style="position:relative;width:\x27+SCENE_W+\x27px;height:\x27+SCENE_H+\x27px;overflow:hidden;border-radius:10px">\x27+
|
|
3912
|
+
isoFloorSvg(ISO_COLS + 2, 4)+
|
|
3913
|
+
agentsHtml+
|
|
3914
|
+
orchHtml+
|
|
3745
3915
|
\x27</div>\x27+
|
|
3746
3916
|
\x27</div>\x27;
|
|
3747
|
-
|
|
3748
|
-
el.innerHTML = html;
|
|
3749
3917
|
}
|
|
3750
3918
|
|
|
3751
3919
|
function studioScrollToAgent(agentLabel) {
|
|
@@ -3791,9 +3959,18 @@ function renderStudioLog() {
|
|
|
3791
3959
|
if (!el) return;
|
|
3792
3960
|
if (!studioState.log.length) { el.style.display = 'none'; return; }
|
|
3793
3961
|
el.style.display = 'block';
|
|
3794
|
-
|
|
3962
|
+
var existingEntries = el.querySelectorAll('.studio-log-entry');
|
|
3963
|
+
studioState.log.forEach(function(e, i) {
|
|
3964
|
+
var isStreaming = false;
|
|
3965
|
+
if (existingEntries[i]) {
|
|
3966
|
+
var tb = existingEntries[i].querySelector('.studio-log-entry__text');
|
|
3967
|
+
if (tb && tb.getAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110)) !== null) {
|
|
3968
|
+
isStreaming = true;
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
if (isStreaming) return; // leave streaming entry DOM untouched
|
|
3795
3972
|
var cls = 'studio-log-entry' + (e.type === 'system' ? ' studio-log-entry--system' : e.type === 'error' ? ' studio-log-entry--error' : '');
|
|
3796
|
-
|
|
3973
|
+
var html = '<div class="' + cls + '">' +
|
|
3797
3974
|
'<div class="studio-log-entry__header">' +
|
|
3798
3975
|
'<span class="studio-log-entry__icon">' + e.icon + '</span>' +
|
|
3799
3976
|
'<span class="studio-log-entry__agent">' + esc(e.agent) + '</span>' +
|
|
@@ -3801,7 +3978,20 @@ function renderStudioLog() {
|
|
|
3801
3978
|
'</div>' +
|
|
3802
3979
|
'<div class="studio-log-entry__text md-body">' + renderMd(e.text) + '</div>' +
|
|
3803
3980
|
'</div>';
|
|
3804
|
-
|
|
3981
|
+
if (existingEntries[i]) {
|
|
3982
|
+
existingEntries[i].outerHTML = html;
|
|
3983
|
+
} else {
|
|
3984
|
+
var div = document.createElement('div');
|
|
3985
|
+
div.innerHTML = html;
|
|
3986
|
+
el.appendChild(div.firstChild);
|
|
3987
|
+
}
|
|
3988
|
+
// refresh reference after replacement
|
|
3989
|
+
existingEntries = el.querySelectorAll('.studio-log-entry');
|
|
3990
|
+
});
|
|
3991
|
+
// remove extra entries (shouldn't happen but be safe)
|
|
3992
|
+
while (el.querySelectorAll('.studio-log-entry').length > studioState.log.length) {
|
|
3993
|
+
el.removeChild(el.lastChild);
|
|
3994
|
+
}
|
|
3805
3995
|
el.scrollTop = el.scrollHeight;
|
|
3806
3996
|
}
|
|
3807
3997
|
|
|
@@ -4261,7 +4451,7 @@ async function runStudio() {
|
|
|
4261
4451
|
for (var i = 0; i < studioState.nodes.length; i++) {
|
|
4262
4452
|
var node = studioState.nodes[i];
|
|
4263
4453
|
studioSetNodeStatus(i, 'running');
|
|
4264
|
-
studioLog(node.label, node.icon, '
|
|
4454
|
+
studioLog(node.label, node.icon, t('starting_agent') || 'Elaborazione in corso...', 'agent');
|
|
4265
4455
|
|
|
4266
4456
|
if (!studioState.running) break; // stopped by user
|
|
4267
4457
|
var stepResult = await runStudioStep(i, node, task, context, planRes.steps[i], studioAbortController ? studioAbortController.signal : null);
|
|
@@ -4356,7 +4546,7 @@ async function runStudio() {
|
|
|
4356
4546
|
// Subsequent calls ONLY update agent states (no innerHTML overwrite).
|
|
4357
4547
|
// ─────────────────────────────────────────────────────────────────────
|
|
4358
4548
|
|
|
4359
|
-
if (!parlBlockBuilt) {
|
|
4549
|
+
if (!parlBlockBuilt || !pb.innerHTML.trim()) {
|
|
4360
4550
|
parlBlockBuilt = true;
|
|
4361
4551
|
|
|
4362
4552
|
// Build agent seat HTML (box + avatar)
|
|
@@ -5365,28 +5555,53 @@ function runStudioStep(idx, node, task, context, stepDef, signal) {
|
|
|
5365
5555
|
tb.textContent = st;
|
|
5366
5556
|
}
|
|
5367
5557
|
} else {
|
|
5368
|
-
// Word-by-word streaming
|
|
5369
|
-
var
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5558
|
+
// Word-by-word streaming: APPEND new chars, never overwrite
|
|
5559
|
+
var renderedLen = parseInt(tb.getAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110)) || \x270\x27, 10);
|
|
5560
|
+
if (renderedLen === 0) {
|
|
5561
|
+
// First token: set up container + cursor
|
|
5562
|
+
tb.innerHTML = \x27\x27;
|
|
5563
|
+
tb.setAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110), \x270\x27);
|
|
5564
|
+
var streamSpan = document.createElement(\x27span\x27);
|
|
5565
|
+
streamSpan.id = \x27streamText_\x27 + idx;
|
|
5566
|
+
streamSpan.style.cssText = \x27font-size:12px;color:var(--text);line-height:1.6;white-space:pre-wrap;word-break:break-word;font-family:var(--font)\x27;
|
|
5567
|
+
tb.appendChild(streamSpan);
|
|
5568
|
+
var cursorEl = document.createElement(\x27span\x27);
|
|
5569
|
+
cursorEl.id = \x27streamCursor_\x27 + idx;
|
|
5570
|
+
cursorEl.style.cssText = \x27display:inline-block;width:2px;height:13px;background:var(--green);margin-left:1px;vertical-align:text-bottom;animation:streamBlink .7s step-end infinite\x27;
|
|
5571
|
+
tb.appendChild(cursorEl);
|
|
5572
|
+
}
|
|
5573
|
+
// Append only newly arrived chars
|
|
5574
|
+
var newChars = output.slice(renderedLen);
|
|
5575
|
+
if (newChars.length > 0) {
|
|
5576
|
+
var stEl = document.getElementById(\x27streamText_\x27 + idx);
|
|
5577
|
+
if (stEl) { stEl.appendChild(document.createTextNode(newChars)); }
|
|
5578
|
+
tb.setAttribute(String.fromCharCode(100,97,116,97,45,114,108,101,110), String(output.length));
|
|
5579
|
+
// Keep studioState.log in sync so renderStudioLog() final call has current text
|
|
5580
|
+
var logLen = studioState.log.length;
|
|
5581
|
+
if (logLen > 0) { studioState.log[logLen - 1].text = output; }
|
|
5582
|
+
}
|
|
5583
|
+
// Update iso thought bubble of the active agent
|
|
5584
|
+
var isoB = document.getElementById(\x27isobubble_\x27+idx);
|
|
5585
|
+
if (isoB) {
|
|
5586
|
+
var wfRaw = output.length > 48 ? output.slice(-48) : output;
|
|
5587
|
+
var wfSafe = wfRaw.replace(/&/g,\x27&\x27).replace(/</g,\x27<\x27).replace(/>/g,\x27>\x27);
|
|
5588
|
+
isoB.className = \x27iso-bubble iso-bubble--active\x27;
|
|
5589
|
+
isoB.innerHTML = wfSafe + \x27<span style="display:inline-block;width:2px;height:8px;background:#6366f1;margin-left:1px;vertical-align:text-bottom;animation:streamBlink .7s step-end infinite">​</span>\x27;
|
|
5590
|
+
}
|
|
5591
|
+
// Update orchestrator bubble with progress
|
|
5592
|
+
var orchB = document.getElementById(\x27wfOrchBubble\x27);
|
|
5593
|
+
if (orchB) {
|
|
5594
|
+
var doneN = studioState.nodes.filter(function(x){return x.status===\x27done\x27;}).length;
|
|
5595
|
+
var totN = studioState.nodes.length;
|
|
5596
|
+
var orchPhrases2 = [\x27Elaboro step \x27+doneN+\x27/\x27+totN, \x27Verifico output...\x27, \x27Coordinamento...\x27, \x27Aspetto risposta...\x27];
|
|
5597
|
+
orchB.textContent = orchPhrases2[Math.floor(output.length/120) % orchPhrases2.length];
|
|
5383
5598
|
}
|
|
5384
|
-
// Update
|
|
5599
|
+
// Update boardroom seat bubble if parliament is active
|
|
5385
5600
|
if (parlActiveAgent) {
|
|
5386
5601
|
var brSafeLbl = parlActiveAgent.replace(new RegExp(\x27[^a-zA-Z0-9_-]\x27,\x27g\x27),\x27_\x27);
|
|
5387
5602
|
var brBubbleEl = document.getElementById(\x27brbubble_\x27+brSafeLbl);
|
|
5388
5603
|
if (brBubbleEl) {
|
|
5389
|
-
var brRaw = output.length >
|
|
5604
|
+
var brRaw = output.length > 48 ? output.slice(-48) : output;
|
|
5390
5605
|
var brSafe = brRaw.replace(/&/g,\x27&\x27).replace(/</g,\x27<\x27).replace(/>/g,\x27>\x27);
|
|
5391
5606
|
brBubbleEl.style.display = \x27\x27;
|
|
5392
5607
|
brBubbleEl.innerHTML = brSafe + \x27<span style="display:inline-block;width:2px;height:8px;background:var(--green);margin-left:1px;vertical-align:text-bottom;animation:streamBlink .7s step-end infinite">​</span>\x27;
|
|
@@ -6196,8 +6411,8 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
6196
6411
|
.br-seat--active .br-seat-box{background:#1e1a45;border-color:var(--sc,#6366f1);box-shadow:0 0 20px rgba(99,102,241,.3),0 0 40px rgba(99,102,241,.08),inset 0 1px 0 rgba(150,130,255,.15)}
|
|
6197
6412
|
.br-seat--active{transform:scale(1.04)}
|
|
6198
6413
|
.br-seat--done .br-seat-box{background:#162516;border-color:#2a4a2a}
|
|
6199
|
-
/* Action bubble above agent */
|
|
6200
|
-
.br-bubble{font-size:
|
|
6414
|
+
/* Action bubble above agent — shows streaming text */
|
|
6415
|
+
.br-bubble{font-size:8px;font-family:var(--mono);padding:3px 8px;border-radius:8px 8px 8px 2px;border:1px solid #3a3060;background:rgba(10,8,20,.88);min-height:14px;text-align:left;line-height:1.45;transition:border-color .3s;word-break:break-word;max-width:100px;white-space:normal;backdrop-filter:blur(4px)}
|
|
6201
6416
|
/* Agent name */
|
|
6202
6417
|
.br-seat-name{font-size:9px;font-family:var(--mono);font-weight:700;text-align:center;white-space:normal;word-break:break-word;max-width:90px;line-height:1.3;margin-top:2px;transition:color .3s}
|
|
6203
6418
|
/* SVG arm animations when agent is active (typing) */
|
|
@@ -6256,13 +6471,21 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
6256
6471
|
.prl-office-plant{position:absolute;bottom:14px;left:4px;width:22px;height:42px;z-index:2;pointer-events:none}
|
|
6257
6472
|
/* Plant right */
|
|
6258
6473
|
.prl-office-plant2{position:absolute;bottom:14px;right:8px;width:22px;height:42px;z-index:2;pointer-events:none}
|
|
6259
|
-
/*
|
|
6474
|
+
/* ── ISOMETRIC JRPG SCENE ── */
|
|
6475
|
+
.iso-scene{background:#0d0b1e;box-shadow:inset 0 0 40px rgba(0,0,0,.6);cursor:default;max-width:100%;overflow-x:auto}
|
|
6476
|
+
.iso-agent{transition:filter .3s}
|
|
6477
|
+
.iso-agent:hover{filter:brightness(1.15)}
|
|
6478
|
+
/* Thought bubble / speech bubble above character */
|
|
6479
|
+
.iso-bubble{font-size:8px;font-family:var(--mono);padding:2px 7px;border-radius:10px 10px 10px 2px;border:1px solid #3a3060;background:rgba(10,8,20,.85);color:#6b7280;white-space:nowrap;max-width:110px;overflow:hidden;text-overflow:ellipsis;line-height:1.4;transition:all .25s;pointer-events:none;backdrop-filter:blur(4px)}
|
|
6480
|
+
.iso-bubble--active{background:rgba(30,20,60,.9);border-color:#6366f1;color:#a5b4fc;animation:isoBubblePop .35s ease;white-space:normal;max-width:110px;word-break:break-word;line-height:1.35}
|
|
6481
|
+
.iso-bubble--orch{font-size:9px;padding:3px 9px;border-radius:12px;border-color:#818cf8;color:#a5b4fc;background:rgba(20,15,50,.9)}
|
|
6482
|
+
@keyframes isoBubblePop{0%{transform:scale(.8) translateY(4px);opacity:.4}100%{transform:scale(1) translateY(0);opacity:1}}
|
|
6483
|
+
.iso-name{font-size:8px;font-family:var(--mono);font-weight:700;letter-spacing:.3px;text-align:center;max-width:80px;white-space:normal;word-break:break-word;line-height:1.3;text-shadow:0 1px 4px rgba(0,0,0,.8);pointer-events:none}
|
|
6484
|
+
/* Desks row — kept for boardroom compat */
|
|
6260
6485
|
.prl-desks-row{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;position:relative;z-index:2;padding-bottom:8px}
|
|
6261
|
-
/* Individual desk card — illuminated */
|
|
6262
6486
|
.prl-desk{display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px 6px 4px;border-radius:12px;background:#1a1535;border:1.5px solid #3a3060;transition:border-color .4s,background .4s,box-shadow .4s;position:relative;min-width:80px;box-shadow:0 2px 8px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.06)}
|
|
6263
6487
|
.prl-desk--active{background:#1e1a45;border-color:var(--dc,#6366f1);box-shadow:0 0 20px rgba(99,102,241,.3),0 0 40px rgba(99,102,241,.1),inset 0 1px 0 rgba(150,130,255,.15)}
|
|
6264
6488
|
.prl-desk--done{border-color:#2a4a2a;background:#162516}
|
|
6265
|
-
/* Action bubble above character */
|
|
6266
6489
|
.prl-action-bubble{font-size:9px;color:#6b7280;font-family:var(--mono);padding:2px 6px;border-radius:8px;background:#111;border:1px solid #2a2a38;min-height:16px;text-align:center;white-space:normal;word-break:break-word;max-width:88px;line-height:1.3;transition:all .3s}
|
|
6267
6490
|
.prl-action-bubble--active{color:var(--dc,#6366f1);border-color:var(--dc,#6366f1);background:rgba(99,102,241,.08);animation:parlBubblePop .4s ease}
|
|
6268
6491
|
@keyframes parlBubblePop{0%{transform:scale(.85);opacity:.5}100%{transform:scale(1);opacity:1}}
|