nothumanallowed 13.5.9 → 13.5.11
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 +308 -247
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.11",
|
|
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.5.
|
|
8
|
+
export const VERSION = '13.5.11';
|
|
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
|
@@ -3781,121 +3781,58 @@ function isoDeskSvg(x, y, accentColor) {
|
|
|
3781
3781
|
\x27</svg>\x27;
|
|
3782
3782
|
}
|
|
3783
3783
|
// Isometric JRPG sprite character — top-down 3/4 perspective, Pokemon-style
|
|
3784
|
+
// Agent emojis — rotate through professional/diverse set
|
|
3785
|
+
var AGENT_EMOJIS = [
|
|
3786
|
+
String.fromCodePoint(0x1F9D1,0x200D,0x1F4BB), // person at laptop
|
|
3787
|
+
String.fromCodePoint(0x1F469,0x200D,0x1F4BC), // woman office worker
|
|
3788
|
+
String.fromCodePoint(0x1F468,0x200D,0x1F4BC), // man office worker
|
|
3789
|
+
String.fromCodePoint(0x1F9D1,0x200D,0x1F52C), // scientist
|
|
3790
|
+
String.fromCodePoint(0x1F469,0x200D,0x1F4BB), // woman technologist
|
|
3791
|
+
String.fromCodePoint(0x1F468,0x200D,0x1F4BB), // man technologist
|
|
3792
|
+
String.fromCodePoint(0x1F9D1,0x200D,0x1F3A8), // artist
|
|
3793
|
+
String.fromCodePoint(0x1F9D1,0x200D,0x2696,0xFE0F), // judge
|
|
3794
|
+
];
|
|
3795
|
+
|
|
3784
3796
|
function isoCharSvg(opts) {
|
|
3785
|
-
var skin = opts.skin || \x27#fbbf24\x27;
|
|
3786
|
-
var shirt = opts.shirt || \x27#4f46e5\x27;
|
|
3787
|
-
var hair = opts.hair || \x27#1a0e08\x27;
|
|
3788
3797
|
var isActive = opts.isActive;
|
|
3789
3798
|
var isDone = opts.isDone;
|
|
3790
3799
|
var scale = opts.scale || 1;
|
|
3791
|
-
var
|
|
3792
|
-
var
|
|
3793
|
-
|
|
3794
|
-
var
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
\
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
\x27<
|
|
3811
|
-
|
|
3812
|
-
\x27
|
|
3813
|
-
\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+
|
|
3814
|
-
\x27<ellipse cx="39" cy="41" rx="4" ry="3" fill="\x27+skin+\x27" transform="rotate(15 39 41)"/>\x27+
|
|
3815
|
-
\x27</g>\x27+
|
|
3816
|
-
// Head
|
|
3817
|
-
\x27<g \x27+headCls+\x27>\x27+
|
|
3818
|
-
\x27<ellipse cx="21" cy="13" rx="11" ry="12" fill="\x27+skin+\x27"/>\x27+
|
|
3819
|
-
\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+
|
|
3820
|
-
\x27<circle cx="16" cy="14" r="1.5" fill="#0a0a14"/>\x27+
|
|
3821
|
-
\x27<circle cx="26" cy="14" r="1.5" fill="#0a0a14"/>\x27+
|
|
3822
|
-
\x27<circle cx="16.7" cy="13" r=".7" fill="rgba(255,255,255,.9)"/>\x27+
|
|
3823
|
-
(isDone ?
|
|
3824
|
-
\x27<path d="M15 20 Q21 24 27 20" stroke="#8b4513" stroke-width="1.5" fill="none" stroke-linecap="round"/>\x27+
|
|
3825
|
-
\x27<path d="M16 20.5 Q21 23 26 20.5 Q21 22 16 20.5" fill="#fff" opacity=".6"/>\x27
|
|
3826
|
-
: isActive ?
|
|
3827
|
-
\x27<path d="M15 19 Q21 21 27 19" stroke="#8b4513" stroke-width="1.4" fill="none" stroke-linecap="round"/>\x27
|
|
3828
|
-
:
|
|
3829
|
-
\x27<path d="M16 20 Q21 22 26 20" stroke="#8b4513" stroke-width="1.2" fill="none" stroke-linecap="round"/>\x27
|
|
3830
|
-
)+
|
|
3831
|
-
\x27</g>\x27+
|
|
3832
|
-
\x27</svg>\x27;
|
|
3800
|
+
var accentColor = opts.accentColor || \x27#6366f1\x27;
|
|
3801
|
+
var idx = opts.emojiIdx;
|
|
3802
|
+
// idx === 99 means orchestrator — use crown+suit combo
|
|
3803
|
+
var emoji = (idx === 99)
|
|
3804
|
+
? (String.fromCodePoint(0x1F451) + String.fromCodePoint(0x1F9D1,0x200D,0x1F4BC))
|
|
3805
|
+
: AGENT_EMOJIS[(idx || 0) % AGENT_EMOJIS.length];
|
|
3806
|
+
var sz = Math.round(52 * scale);
|
|
3807
|
+
var glowColor = isActive ? accentColor : (isDone ? \x27#22c55e\x27 : \x27transparent\x27);
|
|
3808
|
+
var glowFilter = (isActive || isDone) ? (\x27filter:drop-shadow(0 0 8px \x27+glowColor+\x27aa)\x27) : \x27\x27;
|
|
3809
|
+
var badgeHtml = isDone
|
|
3810
|
+
? \x27<div style="position:absolute;top:-4px;right:-4px;width:18px;height:18px;background:#22c55e;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;color:#fff;box-shadow:0 0 6px #22c55e88">✓</div>\x27
|
|
3811
|
+
: (isActive
|
|
3812
|
+
? \x27<div style="position:absolute;top:-4px;right:-4px;width:14px;height:14px;background:\x27+accentColor+\x27;border-radius:50%;animation:statusPulse 1s ease-in-out infinite;box-shadow:0 0 8px \x27+accentColor+\x27"></div>\x27
|
|
3813
|
+
: \x27\x27);
|
|
3814
|
+
var ringStyle = isActive
|
|
3815
|
+
? (\x27outline:2.5px solid \x27+accentColor+\x27;box-shadow:0 0 16px \x27+accentColor+\x27AA\x27)
|
|
3816
|
+
: (isDone ? \x27outline:2px solid #22c55e88\x27 : \x27outline:none\x27);
|
|
3817
|
+
var animClass = isActive ? \x27 prl-head\x27 : \x27\x27;
|
|
3818
|
+
return \x27<div class="iso-char-wrap\x27+animClass+\x27" style="position:relative;display:inline-flex;align-items:center;justify-content:center;width:\x27+sz+\x27px;height:\x27+sz+\x27px;border-radius:50%;background:rgba(255,255,255,.15);\x27+ringStyle+\x27;\x27+glowFilter+\x27;transition:all .3s">\x27+
|
|
3819
|
+
\x27<span style="font-size:\x27+Math.round(36*scale)+\x27px;line-height:1;user-select:none">\x27+emoji+\x27</span>\x27+
|
|
3820
|
+
badgeHtml+
|
|
3821
|
+
\x27</div>\x27;
|
|
3833
3822
|
}
|
|
3834
|
-
// Orchestrator —
|
|
3823
|
+
// Orchestrator — emoji-based, crowned
|
|
3835
3824
|
function isoOrchSvg(hasActive, doneRatio) {
|
|
3836
|
-
|
|
3837
|
-
var
|
|
3838
|
-
var
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
\x27<
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
\x27
|
|
3847
|
-
\x27<ellipse cx="34" cy="74" rx="5" ry="2.5" fill="#0a0a14" transform="rotate(8 34 74)"/>\x27+
|
|
3848
|
-
// Suit body
|
|
3849
|
-
\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+
|
|
3850
|
-
\x27<path d="M14 32 C13 30 16 27 27 25 L27 52 L13 52 Z" fill="#1e1d52"/>\x27+
|
|
3851
|
-
\x27<path d="M27 25 C38 27 41 30 40 32 L41 52 L27 52 Z" fill="#2a2870"/>\x27+
|
|
3852
|
-
// Lapels
|
|
3853
|
-
\x27<path d="M27 25 L21 33 L24 36 L27 29 Z" fill="#1a1940"/>\x27+
|
|
3854
|
-
\x27<path d="M27 25 L33 33 L30 36 L27 29 Z" fill="#1a1940"/>\x27+
|
|
3855
|
-
\x27<path d="M27 29 L24 36 L27 34 L30 36 Z" fill="#f0f0fa"/>\x27+
|
|
3856
|
-
// Tie
|
|
3857
|
-
\x27<path d="M27 33 L26 44 L27 48 L28 44 Z" fill="\x27+mc+\x27"/>\x27+
|
|
3858
|
-
// Arms
|
|
3859
|
-
\x27<g \x27+armCls+\x27 style="transform-origin:14px 35px">\x27+
|
|
3860
|
-
\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+
|
|
3861
|
-
\x27<ellipse cx="6" cy="51" rx="5" ry="3.5" fill="#d4a97a" transform="rotate(-15 6 51)"/>\x27+
|
|
3862
|
-
\x27</g>\x27+
|
|
3863
|
-
\x27<g \x27+armRCls+\x27 style="transform-origin:40px 35px">\x27+
|
|
3864
|
-
\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+
|
|
3865
|
-
// Clipboard
|
|
3866
|
-
\x27<rect x="46" y="30" width="12" height="16" rx="2" fill="#1a1a2e" stroke="\x27+mc+\x2799" stroke-width="1.2"/>\x27+
|
|
3867
|
-
\x27<rect x="49" y="28" width="6" height="4" rx="1" fill="\x27+mc+\x27"/>\x27+
|
|
3868
|
-
\x27<line x1="48" y1="34" x2="56" y2="34" stroke="\x27+mc+\x27cc" stroke-width=".9"/>\x27+
|
|
3869
|
-
\x27<line x1="48" y1="37" x2="56" y2="37" stroke="\x27+mc+\x27aa" stroke-width=".9"/>\x27+
|
|
3870
|
-
\x27<line x1="48" y1="40" x2="54" y2="40" stroke="\x27+mc+\x2788" stroke-width=".9"/>\x27+
|
|
3871
|
-
\x27</g>\x27+
|
|
3872
|
-
// Neck
|
|
3873
|
-
\x27<rect x="24" y="25" width="6" height="5" rx="2" fill="#d4a97a"/>\x27+
|
|
3874
|
-
// Head
|
|
3875
|
-
\x27<ellipse cx="27" cy="14" rx="13" ry="13" fill="#d4a97a"/>\x27+
|
|
3876
|
-
\x27<path d="M14 14 C14 20 18 24 27 25 C36 24 40 20 40 14" fill="#d4a97a"/>\x27+
|
|
3877
|
-
// Hair
|
|
3878
|
-
\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+
|
|
3879
|
-
// Eyes
|
|
3880
|
-
\x27<ellipse cx="22" cy="15" rx="3" ry="3.5" fill="#fff"/>\x27+
|
|
3881
|
-
\x27<ellipse cx="32" cy="15" rx="3" ry="3.5" fill="#fff"/>\x27+
|
|
3882
|
-
\x27<circle cx="22" cy="15.5" r="2" fill="#1e3a6e"/>\x27+
|
|
3883
|
-
\x27<circle cx="32" cy="15.5" r="2" fill="#1e3a6e"/>\x27+
|
|
3884
|
-
\x27<circle cx="22" cy="15.5" r="1.2" fill="#0a0a18"/>\x27+
|
|
3885
|
-
\x27<circle cx="32" cy="15.5" r="1.2" fill="#0a0a18"/>\x27+
|
|
3886
|
-
\x27<circle cx="23" cy="14" r=".8" fill="rgba(255,255,255,.9)"/>\x27+
|
|
3887
|
-
(hasActive ?
|
|
3888
|
-
\x27<path d="M21 21 Q27 25 33 21" stroke="#8b4513" stroke-width="1.8" fill="none" stroke-linecap="round"/>\x27+
|
|
3889
|
-
\x27<ellipse cx="27" cy="22.5" rx="3.5" ry="2" fill="#5a1a0a" opacity=".6"/>\x27
|
|
3890
|
-
:
|
|
3891
|
-
\x27<path d="M21 22 Q27 25 33 22" stroke="#8b4513" stroke-width="1.6" fill="none" stroke-linecap="round"/>\x27
|
|
3892
|
-
)+
|
|
3893
|
-
// Crown
|
|
3894
|
-
\x27<path d="M17 4 L20 9 L27 6 L34 9 L37 4 L27 1 Z" fill="#f59e0b"/>\x27+
|
|
3895
|
-
\x27<circle cx="20" cy="9" r="2" fill="#fbbf24"/>\x27+
|
|
3896
|
-
\x27<circle cx="27" cy="6" r="2" fill="#fbbf24"/>\x27+
|
|
3897
|
-
\x27<circle cx="34" cy="9" r="2" fill="#fbbf24"/>\x27+
|
|
3898
|
-
\x27</svg>\x27;
|
|
3825
|
+
void doneRatio;
|
|
3826
|
+
var orchEmoji = String.fromCodePoint(0x1F9D1, 0x200D, 0x1F4BC); // person in suit
|
|
3827
|
+
var glowColor = hasActive ? \x27#818cf8\x27 : \x27#22c55e\x27;
|
|
3828
|
+
var animClass = hasActive ? \x27 prl-head\x27 : \x27\x27;
|
|
3829
|
+
var crown = String.fromCodePoint(0x1F451); // crown emoji above
|
|
3830
|
+
return \x27<div class="iso-orch-wrap\x27+animClass+\x27" style="position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:2px">\x27+
|
|
3831
|
+
\x27<span style="font-size:18px;line-height:1">\x27+crown+\x27</span>\x27+
|
|
3832
|
+
\x27<div style="position:relative;display:flex;align-items:center;justify-content:center;width:68px;height:68px;border-radius:50%;background:rgba(99,102,241,.15);outline:3px solid \x27+glowColor+\x27;box-shadow:0 0 20px \x27+glowColor+\x27AA">\x27+
|
|
3833
|
+
\x27<span style="font-size:42px;line-height:1;user-select:none">\x27+orchEmoji+\x27</span>\x27+
|
|
3834
|
+
\x27</div>\x27+
|
|
3835
|
+
\x27</div>\x27;
|
|
3899
3836
|
}
|
|
3900
3837
|
|
|
3901
3838
|
// Skin/shirt/hair palette per agent label
|
|
@@ -3907,6 +3844,61 @@ function agentPalette(lbl) {
|
|
|
3907
3844
|
return {skin: skins[i], shirt: shirts[i], hair: hairs[i]};
|
|
3908
3845
|
}
|
|
3909
3846
|
|
|
3847
|
+
// Tool emoji map — specific icon per agent/tool type, fallback to default
|
|
3848
|
+
var TOOL_EMOJI_MAP = {
|
|
3849
|
+
websearch: String.fromCodePoint(0x1F50D),
|
|
3850
|
+
search: String.fromCodePoint(0x1F50D),
|
|
3851
|
+
browser: String.fromCodePoint(0x1F310),
|
|
3852
|
+
email: String.fromCodePoint(0x1F4E7),
|
|
3853
|
+
gmail: String.fromCodePoint(0x1F4E7),
|
|
3854
|
+
calendar: String.fromCodePoint(0x1F4C5),
|
|
3855
|
+
github: String.fromCodePoint(0x1F431),
|
|
3856
|
+
notion: String.fromCodePoint(0x1F4D3),
|
|
3857
|
+
slack: String.fromCodePoint(0x1F4AC),
|
|
3858
|
+
data: String.fromCodePoint(0x1F4CA),
|
|
3859
|
+
analyst: String.fromCodePoint(0x1F4CA),
|
|
3860
|
+
writer: String.fromCodePoint(0x270F,0xFE0F),
|
|
3861
|
+
summary: String.fromCodePoint(0x1F4CB),
|
|
3862
|
+
research: String.fromCodePoint(0x1F52C),
|
|
3863
|
+
canvas: String.fromCodePoint(0x1F3A8),
|
|
3864
|
+
security: String.fromCodePoint(0x1F6E1,0xFE0F),
|
|
3865
|
+
devops: String.fromCodePoint(0x2699,0xFE0F),
|
|
3866
|
+
code: String.fromCodePoint(0x1F4BB),
|
|
3867
|
+
file: String.fromCodePoint(0x1F4C2),
|
|
3868
|
+
drive: String.fromCodePoint(0x1F4BE),
|
|
3869
|
+
maps: String.fromCodePoint(0x1F5FA,0xFE0F),
|
|
3870
|
+
voice: String.fromCodePoint(0x1F3A4),
|
|
3871
|
+
pdf: String.fromCodePoint(0x1F4DC),
|
|
3872
|
+
document: String.fromCodePoint(0x1F4DC),
|
|
3873
|
+
task: String.fromCodePoint(0x2705),
|
|
3874
|
+
contacts: String.fromCodePoint(0x1F4F1),
|
|
3875
|
+
reminder: String.fromCodePoint(0x23F0),
|
|
3876
|
+
news: String.fromCodePoint(0x1F4F0),
|
|
3877
|
+
image: String.fromCodePoint(0x1F5BC,0xFE0F),
|
|
3878
|
+
video: String.fromCodePoint(0x1F3AC),
|
|
3879
|
+
music: String.fromCodePoint(0x1F3B5),
|
|
3880
|
+
translate: String.fromCodePoint(0x1F30D),
|
|
3881
|
+
math: String.fromCodePoint(0x1F9EE),
|
|
3882
|
+
sql: String.fromCodePoint(0x1F5C4,0xFE0F),
|
|
3883
|
+
api: String.fromCodePoint(0x1F517),
|
|
3884
|
+
test: String.fromCodePoint(0x1F9EA),
|
|
3885
|
+
monitor: String.fromCodePoint(0x1F4F6),
|
|
3886
|
+
_default: String.fromCodePoint(0x1F527) // wrench as fallback
|
|
3887
|
+
};
|
|
3888
|
+
|
|
3889
|
+
function getNodeEmoji(n) {
|
|
3890
|
+
var lbl = (n.label || n.agent || '').toLowerCase();
|
|
3891
|
+
var icon = n.icon || '';
|
|
3892
|
+
// Check by label keywords
|
|
3893
|
+
var keys = Object.keys(TOOL_EMOJI_MAP);
|
|
3894
|
+
for (var ki = 0; ki < keys.length; ki++) {
|
|
3895
|
+
if (keys[ki] !== '_default' && lbl.indexOf(keys[ki]) >= 0) return TOOL_EMOJI_MAP[keys[ki]];
|
|
3896
|
+
}
|
|
3897
|
+
// If icon looks like an emoji code point (not HTML entity), use it
|
|
3898
|
+
if (icon && icon.length > 0 && icon.charCodeAt(0) > 127) return icon;
|
|
3899
|
+
return TOOL_EMOJI_MAP._default;
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3910
3902
|
function renderStudioNodes() {
|
|
3911
3903
|
var el = document.getElementById('studioNodes');
|
|
3912
3904
|
if (!el) return;
|
|
@@ -3921,78 +3913,170 @@ function renderStudioNodes() {
|
|
|
3921
3913
|
var totalCount = nodes.length;
|
|
3922
3914
|
var showMaster = hasActive || doneCount > 0;
|
|
3923
3915
|
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3916
|
+
var phaseLabel2 = hasActive
|
|
3917
|
+
? (\x27Workflow in esecuzione \u2014 \x27+doneCount+\x27/\x27+totalCount)
|
|
3918
|
+
: (doneCount===totalCount && totalCount>0 ? \x27Workflow completato\x27 : \x27Workflow pianificato\x27);
|
|
3919
|
+
var phaseColor2 = hasActive ? \x27#6366f1\x27 : (doneCount===totalCount && totalCount>0 ? \x27#22c55e\x27 : \x27#6b7280\x27);
|
|
3920
|
+
|
|
3921
|
+
// ── Layout: all nodes + orchestrator on a grid ────────────────────────────
|
|
3922
|
+
// Include orchestrator as first "station" (desk 0), then all agents
|
|
3923
|
+
// Total stations = nodes.length + 1 (orchestrator)
|
|
3924
|
+
var totalStations = totalCount + 1;
|
|
3925
|
+
// Grid: up to 3 per row, rows fill downward
|
|
3926
|
+
var cols = Math.min(totalStations, 3);
|
|
3927
|
+
var rows = Math.ceil(totalStations / cols);
|
|
3928
|
+
|
|
3929
|
+
// Scene: square, 100% width of parent, dynamic height based on grid rows
|
|
3930
|
+
// Each cell = 160px wide, 180px tall
|
|
3931
|
+
var CELL_W = 160; var CELL_H = 180;
|
|
3932
|
+
var SCENE_W = cols * CELL_W + 40; // +padding
|
|
3933
|
+
var SCENE_H = Math.max(rows * CELL_H + 80, 400);
|
|
3934
|
+
|
|
3935
|
+
// Plant emoji for decoration corners
|
|
3936
|
+
var plantEmoji = String.fromCodePoint(0x1F331); // seedling
|
|
3937
|
+
var bigPlant = String.fromCodePoint(0x1FAB4); // potted plant
|
|
3938
|
+
|
|
3939
|
+
// ── Build station HTML ───────────────────────────────────────────────────
|
|
3940
|
+
var stationsHtml = \x27\x27;
|
|
3941
|
+
|
|
3942
|
+
// Station builder — shared for orchestrator and agents
|
|
3943
|
+
function buildStation(stationIdx, label, emoji, toolEmoji, isOrch, isActive, isDone, isErr, idx) {
|
|
3944
|
+
var col = stationIdx % cols;
|
|
3945
|
+
var row2 = Math.floor(stationIdx / cols);
|
|
3946
|
+
var left = 20 + col * CELL_W + CELL_W/2;
|
|
3947
|
+
var top = 30 + row2 * CELL_H;
|
|
3948
|
+
var zIdx = 100 + row2 * 10 + col;
|
|
3949
|
+
var accentColor = isOrch ? \x27#818cf8\x27 : (isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : (isErr ? \x27#ef4444\x27 : \x27#aaa\x27)));
|
|
3950
|
+
|
|
3951
|
+
// Desk — isometric CSS box using borders
|
|
3952
|
+
var deskHtml = \x27<div class="iso-desk" style="--dc:\x27+accentColor+\x27"></div>\x27;
|
|
3953
|
+
|
|
3954
|
+
// Monitor — small box on desk
|
|
3955
|
+
var monHtml = \x27<div class="iso-monitor" style="border-color:\x27+accentColor+\x2788">\x27+
|
|
3956
|
+
\x27<div class="iso-monitor-screen">\x27+(isOrch?\x27<span style="font-size:10px">🔍</span>\x27:(isDone?\x27<span style="color:#22c55e;font-size:10px">✓</span>\x27:(isActive?\x27<span class="iso-monitor-blink"></span>\x27:\x27<span style="font-size:9px;opacity:.4">■</span>\x27)))+\x27</div>\x27+
|
|
3957
|
+
\x27</div>\x27;
|
|
3958
|
+
|
|
3959
|
+
// Tool badge — the emoji representing what this node does
|
|
3960
|
+
var toolBadge = \x27<div class="iso-tool-badge" title="\x27+esc(label)+\x27">\x27+toolEmoji+\x27</div>\x27;
|
|
3961
|
+
|
|
3962
|
+
// Agent/tool character emoji
|
|
3963
|
+
var charEmojiHtml = isoCharSvg({emojiIdx: isOrch ? 99 : idx, isActive: isActive, isDone: isDone, scale: 1, accentColor: accentColor});
|
|
3964
|
+
|
|
3965
|
+
// Status bubble
|
|
3966
|
+
var bubbleText = isOrch
|
|
3967
|
+
? (hasActive ? (\x27Step \x27+doneCount+\x27/\x27+totalCount) : ((!hasActive && doneCount===totalCount && totalCount>0) ? \x27Completato!\x27 : \x27In attesa\x27))
|
|
3968
|
+
: (isActive ? \x27...lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27)));
|
|
3969
|
+
var bubbleColor = isOrch ? \x27#818cf8\x27 : (isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : \x27#ef4444\x27));
|
|
3970
|
+
var bubbleHtml = (bubbleText || isOrch)
|
|
3971
|
+
? \x27<div class="iso-bubble\x27+(isActive?\x27 iso-bubble--active\x27:\x27\x27)+\x27" id="isobubble_\x27+(isOrch?\x27orch\x27:idx)+\x27" style="border-color:\x27+bubbleColor+\x27;color:\x27+bubbleColor+\x27">\x27+esc(bubbleText)+\x27</div>\x27
|
|
3972
|
+
: \x27<div style="height:22px"></div>\x27;
|
|
3973
|
+
|
|
3974
|
+
// Name badge
|
|
3975
|
+
var nameColor = isDone ? \x27#16a34a\x27 : (isActive ? \x27#6366f1\x27 : (isOrch ? \x27#818cf8\x27 : (isErr ? \x27#dc2626\x27 : \x27#374151\x27)));
|
|
3976
|
+
var nameBg = isDone ? \x27#dcfce7\x27 : (isActive ? \x27#ede9fe\x27 : (isOrch ? \x27#e0e7ff\x27 : \x27#f3f4f6\x27));
|
|
3977
|
+
var nameHtml = \x27<div class="iso-name" style="color:\x27+nameColor+\x27;background:\x27+nameBg+\x27">\x27+(isOrch?\x27\u2666 \x27:\x27\x27)+esc(label.slice(0,18))+\x27</div>\x27;
|
|
3978
|
+
|
|
3979
|
+
// Orchestrator walk animation — walks between desks horizontally
|
|
3980
|
+
var orchWalkStyle = \x27\x27;
|
|
3981
|
+
if (isOrch && hasActive) {
|
|
3982
|
+
var activeIdx = nodes.findIndex(function(nd){return nd.status===\x27running\x27;});
|
|
3983
|
+
if (activeIdx >= 0) {
|
|
3984
|
+
var targetStation = activeIdx + 1; // station index of active agent (orch is 0)
|
|
3985
|
+
var targetCol = targetStation % cols;
|
|
3986
|
+
var targetRow = Math.floor(targetStation / cols);
|
|
3987
|
+
var targetLeft = 20 + targetCol * CELL_W + CELL_W/2;
|
|
3988
|
+
var targetTop = 30 + targetRow * CELL_H;
|
|
3989
|
+
orchWalkStyle = \x27--orch-tx:\x27+(targetLeft - left)+\x27px;--orch-ty:\x27+(targetTop - top)+\x27px\x27;
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
var orchClass = (isOrch && hasActive) ? \x27 iso-orch-walking\x27 : (isOrch && !hasActive && doneCount===totalCount && totalCount>0 ? \x27 iso-orch-done\x27 : \x27\x27);
|
|
3993
|
+
|
|
3994
|
+
var clickHandler = isOrch ? \x27\x27 : \x27onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))"\x27;
|
|
3995
|
+
var dataAttr = isOrch ? \x27\x27 : \x27data-agent-label="\x27+esc(label)+\x27"\x27;
|
|
3996
|
+
|
|
3997
|
+
return \x27<div class="iso-station\x27+orchClass+\x27" \x27+dataAttr+\x27 style="position:absolute;left:\x27+left+\x27px;top:\x27+top+\x27px;z-index:\x27+zIdx+\x27;transform:translateX(-50%);\x27+orchWalkStyle+\x27" \x27+clickHandler+\x27>\x27+
|
|
3998
|
+
bubbleHtml+
|
|
3999
|
+
toolBadge+
|
|
4000
|
+
charEmojiHtml+
|
|
4001
|
+
deskHtml+
|
|
4002
|
+
monHtml+
|
|
4003
|
+
nameHtml+
|
|
4004
|
+
\x27</div>\x27;
|
|
4005
|
+
}
|
|
4006
|
+
|
|
4007
|
+
// Orchestrator station (index 0)
|
|
4008
|
+
var orchIsActive2 = hasActive;
|
|
4009
|
+
var orchDone2 = !hasActive && doneCount === totalCount && totalCount > 0;
|
|
4010
|
+
stationsHtml += buildStation(0, \x27Orchestratore\x27, String.fromCodePoint(0x1F451), String.fromCodePoint(0x1F4CB), true, orchIsActive2, orchDone2, false, -1);
|
|
3927
4011
|
|
|
3928
|
-
|
|
4012
|
+
// Agent/tool stations (index 1..N)
|
|
3929
4013
|
nodes.forEach(function(n, idx) {
|
|
3930
4014
|
var isActive = n.status === \x27running\x27;
|
|
3931
4015
|
var isDone = n.status === \x27done\x27;
|
|
3932
4016
|
var isErr = n.status === \x27error\x27;
|
|
3933
4017
|
var lbl = n.label || n.agent;
|
|
3934
|
-
var
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
// Spread agents evenly across front rows
|
|
3938
|
-
var colStep = ISO_COLS > 1 ? 5 / (ISO_COLS - 1) : 2;
|
|
3939
|
-
var col = (ISO_COLS === 1) ? 2.5 : idx * colStep;
|
|
3940
|
-
var row = 3.5;
|
|
3941
|
-
var pos = isoProject(col, row);
|
|
3942
|
-
var px = pos.x; var py = pos.y + 80;
|
|
3943
|
-
var charScale = 1.1;
|
|
3944
|
-
var zIdx = Math.round(py + 100);
|
|
3945
|
-
|
|
3946
|
-
// Bubble: only show when active (live text) or done (checkmark)
|
|
3947
|
-
var bubbleText = isActive ? \x27...lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27));
|
|
3948
|
-
var bubbleColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : \x27#ef4444\x27);
|
|
3949
|
-
var charSvg = isoCharSvg({skin: pal.skin, shirt: pal.shirt, hair: pal.hair,
|
|
3950
|
-
isActive: isActive, isDone: isDone, scale: charScale, accentColor: accentColor});
|
|
3951
|
-
var charW = Math.round(48 * charScale); var charH = Math.round(64 * charScale);
|
|
3952
|
-
|
|
3953
|
-
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:3px;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;
|
|
3954
|
-
// Bubble — bigger, left-aligned (no mirror issue)
|
|
3955
|
-
if (bubbleText || isActive) {
|
|
3956
|
-
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;min-width:80px;max-width:140px;font-size:10px;padding:4px 10px;text-align:left">\x27+esc(bubbleText)+\x27</div>\x27;
|
|
3957
|
-
} else {
|
|
3958
|
-
agentsHtml += \x27<div class="iso-bubble" id="isobubble_\x27+idx+\x27" style="visibility:hidden;min-width:80px"></div>\x27;
|
|
3959
|
-
}
|
|
3960
|
-
agentsHtml += charSvg;
|
|
3961
|
-
agentsHtml += \x27<div class="iso-name" style="font-size:10px;font-weight:700;color:\x27+(isDone?\x27#22c55e\x27:(isActive?\x27#818cf8\x27:(isErr?\x27#ef4444\x27:\x27#555\x27)))+\x27;text-shadow:0 1px 3px rgba(255,255,255,.8)">\x27+esc(lbl)+\x27</div>\x27;
|
|
3962
|
-
// Desk — lighter wood color for bright office
|
|
3963
|
-
agentsHtml += isoDeskSvg(px, py - charH/2, accentColor);
|
|
3964
|
-
agentsHtml += \x27</div>\x27;
|
|
4018
|
+
var toolEmoji = getNodeEmoji(n);
|
|
4019
|
+
stationsHtml += buildStation(idx + 1, lbl, AGENT_EMOJIS[idx % AGENT_EMOJIS.length], toolEmoji, false, isActive, isDone, isErr, idx);
|
|
3965
4020
|
});
|
|
3966
4021
|
|
|
3967
|
-
// ──
|
|
3968
|
-
var
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
\x27<div class="iso-bubble iso-bubble--orch" id="wfOrchBubble" style="border-color:#6366f1;color:#6366f1;max-width:140px;font-size:10px;padding:4px 10px">\x27+esc(orchStatus)+\x27</div>\x27+
|
|
3978
|
-
isoOrchSvg(hasActive, doneCount / Math.max(totalCount,1))+
|
|
3979
|
-
\x27<div class="prl-master-label" style="color:#6366f1;font-size:9px;font-weight:700;text-shadow:0 1px 3px rgba(255,255,255,.8)">Orchestratore</div>\x27+
|
|
3980
|
-
\x27</div>\x27;
|
|
3981
|
-
}
|
|
4022
|
+
// ── Decorations: plants + door ───────────────────────────────────────────
|
|
4023
|
+
var decoHtml =
|
|
4024
|
+
\x27<div style="position:absolute;bottom:8px;left:8px;font-size:32px;line-height:1;filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))">\x27+bigPlant+\x27</div>\x27+
|
|
4025
|
+
\x27<div style="position:absolute;bottom:8px;right:8px;font-size:32px;line-height:1;filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))">\x27+bigPlant+\x27</div>\x27+
|
|
4026
|
+
\x27<div style="position:absolute;top:8px;right:14px;font-size:22px;line-height:1">\x27+plantEmoji+\x27</div>\x27+
|
|
4027
|
+
// Door on back wall
|
|
4028
|
+
\x27<div style="position:absolute;top:0;left:50%;transform:translateX(-50%);width:38px;height:54px;background:#c8a87a;border:2px solid #a07848;border-radius:4px 4px 0 0;z-index:1">\x27+
|
|
4029
|
+
\x27<div style="position:absolute;right:5px;top:50%;width:6px;height:6px;border-radius:50%;background:#7a5a2a;transform:translateY(-50%)"></div>\x27+
|
|
4030
|
+
\x27<div style="position:absolute;top:4px;left:4px;right:4px;height:16px;background:rgba(255,255,255,.15);border-radius:2px"></div>\x27+
|
|
4031
|
+
\x27</div>\x27;
|
|
3982
4032
|
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4033
|
+
// ── Floor SVG (fills the whole scene) ────────────────────────────────────
|
|
4034
|
+
var floorSvg = \x27<svg viewBox="0 0 \x27+SCENE_W+\x27 \x27+SCENE_H+\x27" width="\x27+SCENE_W+\x27" height="\x27+SCENE_H+\x27" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:0;left:0;z-index:0;pointer-events:none">\x27;
|
|
4035
|
+
// Back wall
|
|
4036
|
+
floorSvg += \x27<rect x="0" y="0" width="\x27+SCENE_W+\x27" height="\x27+Math.round(SCENE_H*0.38)+\x27" fill="#f5f0ea"/>\x27;
|
|
4037
|
+
// Baseboard
|
|
4038
|
+
floorSvg += \x27<rect x="0" y="\x27+Math.round(SCENE_H*0.38-4)+\x27" width="\x27+SCENE_W+\x27" height="6" fill="#d4c4a8" rx="1"/>\x27;
|
|
4039
|
+
// Floor — parquet planks
|
|
4040
|
+
var floorY = Math.round(SCENE_H*0.38);
|
|
4041
|
+
var plankColors = [\x27#c8a06a\x27,\x27#bf9860\x27,\x27#d4aa72\x27,\x27#ba9458\x27,\x27#c4a068\x27];
|
|
4042
|
+
var plankH = 28; var plankW = 80;
|
|
4043
|
+
for (var fy = floorY; fy < SCENE_H; fy += plankH) {
|
|
4044
|
+
var rowOff = (Math.floor((fy-floorY)/plankH) % 2) * (plankW/2);
|
|
4045
|
+
for (var fx = -plankW + rowOff; fx < SCENE_W + plankW; fx += plankW) {
|
|
4046
|
+
var pc = plankColors[Math.abs(Math.round(fx/plankW + fy/plankH)) % plankColors.length];
|
|
4047
|
+
floorSvg += \x27<rect x="\x27+fx+\x27" y="\x27+fy+\x27" width="\x27+(plankW-1)+\x27" height="\x27+(plankH-1)+\x27" fill="\x27+pc+\x27" rx="1"/>\x27;
|
|
4048
|
+
// Grain line
|
|
4049
|
+
floorSvg += \x27<line x1="\x27+(fx+plankW*0.35)+\x27" y1="\x27+fy+\x27" x2="\x27+(fx+plankW*0.35)+\x27" y2="\x27+(fy+plankH-1)+\x27" stroke="rgba(0,0,0,.05)" stroke-width="1"/>\x27;
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
// Window on back wall
|
|
4053
|
+
floorSvg += \x27<rect x="20" y="18" width="60" height="50" rx="3" fill="#bbd8f5" stroke="#a8c4dc" stroke-width="2"/>\x27;
|
|
4054
|
+
floorSvg += \x27<line x1="50" y1="18" x2="50" y2="68" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
|
|
4055
|
+
floorSvg += \x27<line x1="20" y1="43" x2="80" y2="43" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
|
|
4056
|
+
floorSvg += \x27<rect x="20" y="18" width="60" height="50" rx="3" fill="rgba(255,255,255,.15)"/>\x27;
|
|
4057
|
+
if (SCENE_W > 350) {
|
|
4058
|
+
floorSvg += \x27<rect x="\x27+(SCENE_W-100)+\x27" y="18" width="60" height="50" rx="3" fill="#bbd8f5" stroke="#a8c4dc" stroke-width="2"/>\x27;
|
|
4059
|
+
floorSvg += \x27<line x1="\x27+(SCENE_W-70)+\x27" y1="18" x2="\x27+(SCENE_W-70)+\x27" y2="68" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
|
|
4060
|
+
floorSvg += \x27<line x1="\x27+(SCENE_W-100)+\x27" y1="43" x2="\x27+(SCENE_W-40)+\x27" y2="43" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
|
|
4061
|
+
}
|
|
4062
|
+
// Chandelier
|
|
4063
|
+
var chandX = Math.round(SCENE_W/2);
|
|
4064
|
+
floorSvg += \x27<line x1="\x27+chandX+\x27" y1="0" x2="\x27+chandX+\x27" y2="24" stroke="#999" stroke-width="2"/>\x27;
|
|
4065
|
+
floorSvg += \x27<ellipse cx="\x27+chandX+\x27" cy="28" rx="28" ry="8" fill="#e8d980" stroke="#c8b840" stroke-width="1.5"/>\x27;
|
|
4066
|
+
floorSvg += \x27<circle cx="\x27+(chandX-18)+\x27" cy="32" r="5" fill="#fff8c0" filter="url(#bGlow)"/>\x27;
|
|
4067
|
+
floorSvg += \x27<circle cx="\x27+chandX+\x27" cy="34" r="5" fill="#fff8c0" filter="url(#bGlow)"/>\x27;
|
|
4068
|
+
floorSvg += \x27<circle cx="\x27+(chandX+18)+\x27" cy="32" r="5" fill="#fff8c0" filter="url(#bGlow)"/>\x27;
|
|
4069
|
+
floorSvg += \x27<defs><filter id="bGlow" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="4" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs>\x27;
|
|
4070
|
+
floorSvg += \x27</svg>\x27;
|
|
3987
4071
|
|
|
3988
4072
|
el.innerHTML =
|
|
3989
4073
|
\x27<div class="prl-wrap" style="border-color:\x27+phaseColor2+\x2744;padding-bottom:8px">\x27+
|
|
3990
4074
|
\x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor2+\x27">\x27+phaseLabel2+\x27</span></div>\x27+
|
|
3991
|
-
\x27<div
|
|
3992
|
-
\x27<div class="iso-scene" style="position:relative;width:\x27+SCENE_W+\x27px;min-width:\x27+SCENE_W+\x27px;height:\x27+SCENE_H+\x27px
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
4075
|
+
\x27<div class="iso-scene-wrap">\x27+
|
|
4076
|
+
\x27<div class="iso-scene" style="position:relative;width:\x27+SCENE_W+\x27px;min-width:\x27+SCENE_W+\x27px;height:\x27+SCENE_H+\x27px">\x27+
|
|
4077
|
+
floorSvg+
|
|
4078
|
+
decoHtml+
|
|
4079
|
+
stationsHtml+
|
|
3996
4080
|
\x27</div>\x27+
|
|
3997
4081
|
\x27</div>\x27+
|
|
3998
4082
|
\x27</div>\x27;
|
|
@@ -4632,84 +4716,35 @@ async function runStudio() {
|
|
|
4632
4716
|
if (!parlBlockBuilt || !pb.innerHTML.trim()) {
|
|
4633
4717
|
parlBlockBuilt = true;
|
|
4634
4718
|
|
|
4635
|
-
// Build agent seat HTML (
|
|
4636
|
-
function buildSeat(prop) {
|
|
4719
|
+
// Build agent seat HTML (emoji avatar)
|
|
4720
|
+
function buildSeat(prop, seatIdx) {
|
|
4637
4721
|
var lbl = prop.label || prop.agent;
|
|
4638
|
-
var
|
|
4639
|
-
var
|
|
4640
|
-
var
|
|
4641
|
-
|
|
4642
|
-
var
|
|
4643
|
-
var safeLbl = lbl.replace(/[^a-zA-Z0-9_-]/g,\x27_\x27);
|
|
4644
|
-
// Mini agent SVG (seated, top-down perspective hint)
|
|
4645
|
-
var agentSvg = \x27<svg viewBox="0 0 44 52" width="44" height="52" xmlns="http://www.w3.org/2000/svg">\x27+
|
|
4646
|
-
// Chair back
|
|
4647
|
-
\x27<rect x="6" y="2" width="32" height="6" rx="3" fill="#2a2050" stroke="#3a3070" stroke-width="1"/>\x27+
|
|
4648
|
-
// Chair seat
|
|
4649
|
-
\x27<rect x="6" y="32" width="32" height="12" rx="3" fill="#221840" stroke="#3a3060" stroke-width="1"/>\x27+
|
|
4650
|
-
// Body / torso
|
|
4651
|
-
\x27<rect x="14" y="8" width="16" height="22" rx="4" fill="\x27+shirtC+\x27" opacity=".9"/>\x27+
|
|
4652
|
-
// Head
|
|
4653
|
-
\x27<circle cx="22" cy="5" r="7" fill="\x27+skin+\x27"/>\x27+
|
|
4654
|
-
// Eyes
|
|
4655
|
-
\x27<circle cx="19.5" cy="4.5" r="1.2" fill="#0a0a14"/>\x27+
|
|
4656
|
-
\x27<circle cx="24.5" cy="4.5" r="1.2" fill="#0a0a14"/>\x27+
|
|
4657
|
-
// Arms on desk
|
|
4658
|
-
\x27<rect x="7" y="26" width="9" height="5" rx="2" fill="\x27+skin+\x27" class="br-arm-l"/>\x27+
|
|
4659
|
-
\x27<rect x="28" y="26" width="9" height="5" rx="2" fill="\x27+skin+\x27" class="br-arm-r"/>\x27+
|
|
4660
|
-
// Monitor on desk in front of agent
|
|
4661
|
-
\x27<rect x="12" y="37" width="20" height="13" rx="2" fill="#141028" stroke="#3a3070" stroke-width="1"/>\x27+
|
|
4662
|
-
\x27<rect x="13" y="38" width="18" height="11" rx="1" fill="rgba(90,80,180,.35)"/>\x27+
|
|
4663
|
-
\x27<line x1="14" y1="41" x2="30" y2="41" stroke="#9090cc" stroke-width=".8" opacity=".8"/>\x27+
|
|
4664
|
-
\x27<line x1="14" y1="44" x2="28" y2="44" stroke="#7070aa" stroke-width=".8" opacity=".6"/>\x27+
|
|
4665
|
-
// Agent badge
|
|
4666
|
-
\x27<circle cx="22" cy="13" r="5" fill="#0f0f1e" stroke="\x27+shirtC+\x2780" stroke-width="1.2"/>\x27+
|
|
4667
|
-
\x27<text x="22" y="16" text-anchor="middle" font-size="6" font-family="system-ui">\x27+ico+\x27</text>\x27+
|
|
4668
|
-
\x27</svg>\x27;
|
|
4722
|
+
var safeLbl = lbl.replace(new RegExp('[^a-zA-Z0-9_-]','g'),\x27_\x27);
|
|
4723
|
+
var emojiIdx = Math.abs(lbl.charCodeAt(0)+(lbl.charCodeAt(lbl.length-1)||0)) % AGENT_EMOJIS.length;
|
|
4724
|
+
var agentEmoji = AGENT_EMOJIS[emojiIdx];
|
|
4725
|
+
void seatIdx;
|
|
4726
|
+
var agentAvatar = \x27<div style="font-size:36px;line-height:1;user-select:none;filter:drop-shadow(0 2px 4px rgba(0,0,0,.3))">\x27+agentEmoji+\x27</div>\x27;
|
|
4669
4727
|
return \x27<div class="br-seat" id="brseat_\x27+safeLbl+\x27" data-lbl="\x27+esc(lbl)+\x27">\x27+
|
|
4670
4728
|
\x27<div class="br-seat-box">\x27+
|
|
4671
4729
|
\x27<div class="br-bubble" id="brbubble_\x27+safeLbl+\x27"></div>\x27+
|
|
4672
|
-
|
|
4730
|
+
agentAvatar+
|
|
4673
4731
|
\x27<div class="br-seat-name" id="brname_\x27+safeLbl+\x27">\x27+esc(lbl)+\x27</div>\x27+
|
|
4674
4732
|
\x27</div>\x27+
|
|
4675
4733
|
\x27</div>\x27;
|
|
4676
4734
|
}
|
|
4677
4735
|
|
|
4678
4736
|
// Arrange seats in a circle around center table
|
|
4679
|
-
// Positions computed from CSS: use CSS custom properties per seat index
|
|
4680
4737
|
var seatsHtml = proposals.map(buildSeat).join(\x27\x27);
|
|
4681
4738
|
|
|
4682
|
-
// Orchestrator at center (
|
|
4683
|
-
var
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
\x27<
|
|
4689
|
-
\x27
|
|
4690
|
-
|
|
4691
|
-
// Tie
|
|
4692
|
-
\x27<path d="M22 22 L21 36 L22 40 L23 36 Z" fill="#818cf8"/>\x27+
|
|
4693
|
-
// Arms gesturing (spread wide — presenting)
|
|
4694
|
-
\x27<path d="M10 28 C4 30 1 36 2 41 C3 44 6 44 8 42 C10 40 11 36 12 32 C13 30 11 27 10 28" fill="#252464" class="br-orch-arm-l"/>\x27+
|
|
4695
|
-
\x27<path d="M34 28 C40 30 43 36 42 41 C41 44 38 44 36 42 C34 40 33 36 32 32 C31 30 33 27 34 28" fill="#252464" class="br-orch-arm-r"/>\x27+
|
|
4696
|
-
// Head
|
|
4697
|
-
\x27<circle cx="22" cy="13" r="9" fill="#fbbf24"/>\x27+
|
|
4698
|
-
\x27<circle cx="19" cy="12" r="1.5" fill="#0a0a14"/>\x27+
|
|
4699
|
-
\x27<circle cx="25" cy="12" r="1.5" fill="#0a0a14"/>\x27+
|
|
4700
|
-
\x27<circle cx="20" cy="11" r=".6" fill="rgba(255,255,255,.8)"/>\x27+
|
|
4701
|
-
\x27<circle cx="26" cy="11" r=".6" fill="rgba(255,255,255,.8)"/>\x27+
|
|
4702
|
-
// Mouth — speaking
|
|
4703
|
-
\x27<path d="M18 16 Q22 20 26 16" stroke="#8b4513" stroke-width="1.6" fill="none" stroke-linecap="round"/>\x27+
|
|
4704
|
-
// NHA badge
|
|
4705
|
-
\x27<circle cx="16" cy="30" r="3" fill="#0d0d1e" stroke="#818cf888" stroke-width="1"/>\x27+
|
|
4706
|
-
\x27<text x="16" y="32.5" text-anchor="middle" font-size="3.5" fill="#818cf8">N</text>\x27+
|
|
4707
|
-
// Crown / authority marker
|
|
4708
|
-
\x27<path d="M15 3 L17 8 L22 5 L27 8 L29 3 L22 0 Z" fill="#f59e0b"/>\x27+
|
|
4709
|
-
\x27<circle cx="17" cy="8" r="1.5" fill="#fbbf24"/>\x27+
|
|
4710
|
-
\x27<circle cx="22" cy="5" r="1.5" fill="#fbbf24"/>\x27+
|
|
4711
|
-
\x27<circle cx="27" cy="8" r="1.5" fill="#fbbf24"/>\x27+
|
|
4712
|
-
\x27</svg>\x27;
|
|
4739
|
+
// Orchestrator at center — emoji (crowned suit)
|
|
4740
|
+
var orchEmoji = String.fromCodePoint(0x1F9D1,0x200D,0x1F4BC);
|
|
4741
|
+
var crownEmoji = String.fromCodePoint(0x1F451);
|
|
4742
|
+
var orchSvgEl = crownEmoji; // crown above orchestrator emoji — not SVG anymore
|
|
4743
|
+
var orchSvg = \x27<div style="display:flex;flex-direction:column;align-items:center;gap:2px">\x27+
|
|
4744
|
+
\x27<span style="font-size:22px;line-height:1">\x27+crownEmoji+\x27</span>\x27+
|
|
4745
|
+
\x27<div style="font-size:52px;line-height:1;filter:drop-shadow(0 0 12px #818cf8AA);user-select:none">\x27+orchEmoji+\x27</div>\x27+
|
|
4746
|
+
\x27</div>\x27;
|
|
4747
|
+
void orchSvgEl;
|
|
4713
4748
|
|
|
4714
4749
|
// Center table (SVG oval)
|
|
4715
4750
|
var tableSvg = \x27<svg viewBox="0 0 160 80" width="160" height="80" xmlns="http://www.w3.org/2000/svg">\x27+
|
|
@@ -5972,16 +6007,18 @@ function renderStudio(el) {
|
|
|
5972
6007
|
'</div>' +
|
|
5973
6008
|
|
|
5974
6009
|
// ── AGENT SIDEBAR ──
|
|
5975
|
-
'<div
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
'<
|
|
5979
|
-
|
|
6010
|
+
'<div style="display:flex;flex-direction:column;gap:12px;width:220px;flex-shrink:0;position:sticky;top:16px;align-self:flex-start">' +
|
|
6011
|
+
'<div class="studio-tools-panel">' +
|
|
6012
|
+
// Tab bar
|
|
6013
|
+
'<div style="display:flex;gap:0;margin-bottom:10px;border:1px solid var(--border);border-radius:6px;overflow:hidden">' +
|
|
6014
|
+
'<button id="sideTabTools" onclick="studioSideTab(\\x27tools\\x27)" style="flex:1;padding:5px;font-size:10px;font-weight:600;background:var(--green3);color:#fff;border:none;cursor:pointer">🔧 Tools</button>' +
|
|
6015
|
+
'<button id="sideTabAgents" onclick="studioSideTab(\\x27agents\\x27)" style="flex:1;padding:5px;font-size:10px;font-weight:600;background:var(--bg3);color:var(--dim);border:none;cursor:pointer">🤖 Agents</button>' +
|
|
6016
|
+
'</div>' +
|
|
6017
|
+
'<div style="font-size:9px;color:var(--dim);margin-bottom:8px">Click to add to pipeline</div>' +
|
|
6018
|
+
'<div id="sideToolsList">'+toolsHtml+'</div>' +
|
|
6019
|
+
'<div id="sideAgentsList" style="display:none">'+specialistHtml+'</div>' +
|
|
5980
6020
|
'</div>' +
|
|
5981
|
-
'<div style="
|
|
5982
|
-
'<div id="sideToolsList">'+toolsHtml+'</div>' +
|
|
5983
|
-
'<div id="sideAgentsList" style="display:none">'+specialistHtml+'</div>' +
|
|
5984
|
-
'<div id="studioSessionsBar" style="margin-top:16px;display:none"></div>' +
|
|
6021
|
+
'<div id="studioSessionsBar" style="display:none;border:1px solid var(--border);border-radius:10px;padding:12px;background:var(--bg2)"></div>' +
|
|
5985
6022
|
'</div>' +
|
|
5986
6023
|
'</div>';
|
|
5987
6024
|
|
|
@@ -6646,19 +6683,43 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
6646
6683
|
/* Plant right */
|
|
6647
6684
|
.prl-office-plant2{position:absolute;bottom:14px;right:8px;width:22px;height:42px;z-index:2;pointer-events:none}
|
|
6648
6685
|
/* ── ISOMETRIC JRPG SCENE ── */
|
|
6649
|
-
.iso-scene{
|
|
6686
|
+
.iso-scene-wrap{width:100%;overflow-x:auto;display:flex;justify-content:center}
|
|
6687
|
+
.iso-scene{background:#f0ede6;cursor:default;overflow:hidden;border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,.18)}
|
|
6688
|
+
/* ── Station layout (new grid-based office) ── */
|
|
6689
|
+
.iso-station{display:flex;flex-direction:column;align-items:center;gap:2px;cursor:pointer;transition:filter .2s}
|
|
6690
|
+
.iso-station:hover{filter:brightness(1.08)}
|
|
6691
|
+
.iso-station.iso-orch-walking{animation:orchWalk 2.2s ease-in-out infinite alternate}
|
|
6692
|
+
@keyframes orchWalk{0%{transform:translateX(-50%)}100%{transform:translateX(calc(-50% + var(--orch-tx,0px))) translateY(var(--orch-ty,0px))}}
|
|
6693
|
+
.iso-station.iso-orch-done{animation:orchDone .6s ease forwards}
|
|
6694
|
+
@keyframes orchDone{0%{transform:translateX(-50%) scale(1)}50%{transform:translateX(-50%) scale(1.15)}100%{transform:translateX(-50%) scale(1)}}
|
|
6695
|
+
/* Desk */
|
|
6696
|
+
.iso-desk{width:90px;height:18px;background:linear-gradient(180deg,#d4a448 0%,#b8832a 100%);border-radius:4px 4px 2px 2px;box-shadow:0 4px 0 #8a5e18,0 6px 8px rgba(0,0,0,.25);border:1px solid #c49038;position:relative;margin-top:2px}
|
|
6697
|
+
.iso-desk::after{content:'';position:absolute;bottom:-4px;left:6px;right:6px;height:4px;background:#8a5e18;border-radius:0 0 3px 3px}
|
|
6698
|
+
/* Monitor on desk */
|
|
6699
|
+
.iso-monitor{width:52px;height:38px;background:#1a1a2c;border:2px solid #3a3070;border-radius:4px;position:absolute;top:-44px;left:50%;transform:translateX(-50%);display:flex;align-items:center;justify-content:center}
|
|
6700
|
+
.iso-monitor::before{content:'';position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);width:8px;height:6px;background:#252436;border-radius:0 0 2px 2px}
|
|
6701
|
+
.iso-monitor-screen{width:42px;height:28px;background:rgba(80,60,180,.3);border-radius:2px;display:flex;align-items:center;justify-content:center}
|
|
6702
|
+
.iso-monitor-blink{width:6px;height:6px;border-radius:50%;background:#6366f1;animation:monBlink .8s ease-in-out infinite}
|
|
6703
|
+
@keyframes monBlink{0%,100%{opacity:1;box-shadow:0 0 6px #6366f1}50%{opacity:.3;box-shadow:none}}
|
|
6704
|
+
/* Tool badge emoji floating above desk */
|
|
6705
|
+
.iso-tool-badge{font-size:18px;line-height:1;filter:drop-shadow(0 2px 4px rgba(0,0,0,.3));margin-bottom:-2px;user-select:none}
|
|
6650
6706
|
/* Animated status chip for [bracket tokens] */
|
|
6651
6707
|
.iso-status-chip{display:inline-flex;align-items:center;gap:6px;background:rgba(99,102,241,.1);border:1px solid rgba(99,102,241,.3);border-radius:20px;padding:3px 10px;font-size:11px;font-family:var(--mono);color:#818cf8;animation:statusPulse 2s ease-in-out infinite}
|
|
6652
6708
|
@keyframes statusPulse{0%,100%{opacity:.7;border-color:rgba(99,102,241,.3)}50%{opacity:1;border-color:rgba(99,102,241,.7);box-shadow:0 0 8px rgba(99,102,241,.3)}}
|
|
6653
6709
|
.iso-status-dot{width:6px;height:6px;border-radius:50%;background:#6366f1;animation:dotBounce 1s ease-in-out infinite}
|
|
6654
6710
|
.iso-agent{transition:filter .3s}
|
|
6655
|
-
.iso-agent:hover{filter:brightness(1.
|
|
6711
|
+
.iso-agent:hover{filter:brightness(1.1) saturate(1.2)}
|
|
6712
|
+
.iso-char-wrap{transition:transform .2s,box-shadow .3s}
|
|
6713
|
+
.iso-char-wrap.prl-head{animation:isoCharBob 1.2s ease-in-out infinite}
|
|
6714
|
+
@keyframes isoCharBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
|
|
6715
|
+
.iso-orch-wrap{transition:transform .2s}
|
|
6716
|
+
.iso-orch-wrap.prl-head{animation:isoCharBob 1.4s ease-in-out infinite}
|
|
6656
6717
|
/* Thought bubble / speech bubble above character */
|
|
6657
6718
|
.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)}
|
|
6658
6719
|
.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}
|
|
6659
6720
|
.iso-bubble--orch{font-size:9px;padding:3px 9px;border-radius:12px;border-color:#818cf8;color:#a5b4fc;background:rgba(20,15,50,.9)}
|
|
6660
6721
|
@keyframes isoBubblePop{0%{transform:scale(.8) translateY(4px);opacity:.4}100%{transform:scale(1) translateY(0);opacity:1}}
|
|
6661
|
-
.iso-name{font-size:
|
|
6722
|
+
.iso-name{font-size:10px;font-family:var(--mono);font-weight:700;letter-spacing:.3px;text-align:center;max-width:90px;white-space:normal;word-break:break-word;line-height:1.3;background:rgba(255,255,255,.85);border-radius:6px;padding:2px 6px;pointer-events:none;backdrop-filter:blur(4px)}
|
|
6662
6723
|
/* Desks row — kept for boardroom compat */
|
|
6663
6724
|
.prl-desks-row{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;position:relative;z-index:2;padding-bottom:8px}
|
|
6664
6725
|
.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)}
|
|
@@ -6734,7 +6795,7 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
6734
6795
|
.studio-result__body{font-size:13px;color:var(--text);word-wrap:break-word;line-height:1.7}
|
|
6735
6796
|
.studio-example-btn{display:inline-block;padding:5px 12px;border:1px solid var(--border2);border-radius:20px;font-size:10px;color:var(--dim);cursor:pointer;background:none;margin:0 4px 6px 0;transition:all .15s}
|
|
6736
6797
|
.studio-example-btn:hover{border-color:var(--green3);color:var(--green);background:var(--greendim)}
|
|
6737
|
-
.studio-tools-panel{width:
|
|
6798
|
+
.studio-tools-panel{width:100%;border:1px solid var(--border);border-radius:10px;padding:12px;background:var(--bg2);max-height:calc(100vh - 200px);overflow-y:auto}
|
|
6738
6799
|
.studio-tool-item{display:flex;align-items:flex-start;gap:8px;padding:8px;border-radius:6px;cursor:pointer;transition:background .15s;margin-bottom:4px}
|
|
6739
6800
|
.studio-tool-item:hover{background:var(--bg3);border-radius:6px}
|
|
6740
6801
|
.studio-tool-icon{font-size:16px;flex-shrink:0;margin-top:1px}
|