nothumanallowed 13.5.2 → 13.5.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "13.5.2",
3
+ "version": "13.5.4",
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.2';
8
+ export const VERSION = '13.5.4';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -3308,6 +3308,8 @@ var studioState = {
3308
3308
  };
3309
3309
 
3310
3310
  var studioAbortController = null;
3311
+ var parlActiveAgent = null; // active agent label during parliament streaming
3312
+ var parlDoneAgents = {}; // set of completed agent labels during parliament
3311
3313
 
3312
3314
  function stopStudio() {
3313
3315
  if (!studioState.running) return;
@@ -4193,6 +4195,8 @@ async function runStudio() {
4193
4195
  studioState.running = true;
4194
4196
  studioState.planned = false;
4195
4197
  // Keep attachmentContext — it was loaded before hitting Run
4198
+ parlActiveAgent = null;
4199
+ parlDoneAgents = {};
4196
4200
  var parlBlockEl = document.getElementById('studioParliamentBlock');
4197
4201
  if (parlBlockEl) parlBlockEl.style.display = 'none';
4198
4202
  renderStudioNodes();
@@ -4324,40 +4328,240 @@ async function runStudio() {
4324
4328
  renderStudioNodes();
4325
4329
 
4326
4330
  // ── Parliament visual block ──────────────────────────────────────
4327
- // Track active R2 agent for visual block
4328
- var parlActiveAgent = null;
4329
- var parlDoneAgents = {};
4331
+ // Track active R2 agent for visual block (module-level vars)
4332
+ parlActiveAgent = null;
4333
+ parlDoneAgents = {};
4334
+
4335
+ // ── Parliament boardroom: first call builds DOM, subsequent calls only update state ──
4336
+ var parlBlockBuilt = false;
4330
4337
 
4331
4338
  function renderParlBlock(phase, activeLabel, convergence) {
4332
4339
  var pb = document.getElementById(\x27studioParliamentBlock\x27);
4333
4340
  if (!pb) return;
4334
4341
  pb.style.display = \x27block\x27;
4335
- // Always in normal document flow — no fixed/absolute positioning
4336
- pb.style.position = \x27\x27; pb.style.bottom = \x27\x27; pb.style.left = \x27\x27;
4337
- pb.style.transform = \x27\x27; pb.style.width = \x27\x27;
4338
- pb.style.top = \x27\x27; pb.style.zIndex = \x27\x27; pb.style.boxShadow = \x27\x27;
4339
- pb.style.maxWidth = \x27\x27;
4340
-
4341
- // ── OFFICE CARTOON ANIMATION ─────────────────────────────────────────
4342
- // Each agent = a character at a desk doing visible work.
4343
- // Documents fly between agents during R2. MASTER walks around in R1.
4342
+
4344
4343
  var phaseColor = {r1:\x27#6366f1\x27,r2:\x27#22d3ee\x27,r3:\x27#f59e0b\x27,done:\x27#22c55e\x27}[phase]||\x27#6366f1\x27;
4345
4344
  var phaseLabel = {
4346
- r1:\x27Round 1 \u2014 Ogni agente analizza il task in autonomia\x27,
4347
- r2:\x27Round 2 \u2014 Gli agenti si scambiano le analisi e le raffinano\x27,
4348
- r3:\x27Round 3 \u2014 HERALD media le posizioni divergenti\x27,
4345
+ r1:\x27Round 1 \u2014 Ogni agente analizza\x27,
4346
+ r2:\x27Round 2 \u2014 Cross-reading e raffinamento\x27,
4347
+ r3:\x27Round 3 \u2014 HERALD media le divergenze\x27,
4349
4348
  done:\x27Deliberazione completata\x27
4350
4349
  }[phase]||\x27\x27;
4351
-
4352
4350
  var n = proposals.length;
4353
4351
  var doneCount = Object.keys(parlDoneAgents).length;
4354
4352
  var progressPct = n > 0 ? Math.round(doneCount / n * 100) : 0;
4355
4353
 
4356
- // ── Build one desk+character card per agent ───────────────────────
4357
- // Character is SVG-drawn inline: head + body + arms + desk.
4358
- // Active = character types (arms animate). Done = character leans back, checkmark.
4359
- // R2 active = character holds document up and turns head.
4354
+ // ─────────────────────────────────────────────────────────────────────
4355
+ // BOARDROOM 3D first call builds the full DOM structure.
4356
+ // Subsequent calls ONLY update agent states (no innerHTML overwrite).
4357
+ // ─────────────────────────────────────────────────────────────────────
4358
+
4359
+ if (!parlBlockBuilt) {
4360
+ parlBlockBuilt = true;
4361
+
4362
+ // Build agent seat HTML (box + avatar)
4363
+ function buildSeat(prop) {
4364
+ var lbl = prop.label || prop.agent;
4365
+ var ico = prop.icon || String.fromCharCode(9632);
4366
+ var skinColors = [\x27#fbbf24\x27,\x27#f97316\x27,\x27#a78bfa\x27,\x27#34d399\x27,\x27#60a5fa\x27,\x27#f472b6\x27];
4367
+ var skinIdx = Math.abs(lbl.charCodeAt(0)+(lbl.charCodeAt(lbl.length-1)||0)) % skinColors.length;
4368
+ var skin = skinColors[skinIdx];
4369
+ var shirtC = [\x27#4f46e5\x27,\x27#0891b2\x27,\x27#7c3aed\x27,\x27#059669\x27,\x27#dc2626\x27,\x27#d97706\x27][skinIdx];
4370
+ var safeLbl = lbl.replace(/[^a-zA-Z0-9_-]/g,\x27_\x27);
4371
+ // Mini agent SVG (seated, top-down perspective hint)
4372
+ var agentSvg = \x27<svg viewBox="0 0 44 52" width="44" height="52" xmlns="http://www.w3.org/2000/svg">\x27+
4373
+ // Chair back
4374
+ \x27<rect x="6" y="2" width="32" height="6" rx="3" fill="#2a2050" stroke="#3a3070" stroke-width="1"/>\x27+
4375
+ // Chair seat
4376
+ \x27<rect x="6" y="32" width="32" height="12" rx="3" fill="#221840" stroke="#3a3060" stroke-width="1"/>\x27+
4377
+ // Body / torso
4378
+ \x27<rect x="14" y="8" width="16" height="22" rx="4" fill="\x27+shirtC+\x27" opacity=".9"/>\x27+
4379
+ // Head
4380
+ \x27<circle cx="22" cy="5" r="7" fill="\x27+skin+\x27"/>\x27+
4381
+ // Eyes
4382
+ \x27<circle cx="19.5" cy="4.5" r="1.2" fill="#0a0a14"/>\x27+
4383
+ \x27<circle cx="24.5" cy="4.5" r="1.2" fill="#0a0a14"/>\x27+
4384
+ // Arms on desk
4385
+ \x27<rect x="7" y="26" width="9" height="5" rx="2" fill="\x27+skin+\x27" class="br-arm-l"/>\x27+
4386
+ \x27<rect x="28" y="26" width="9" height="5" rx="2" fill="\x27+skin+\x27" class="br-arm-r"/>\x27+
4387
+ // Monitor on desk in front of agent
4388
+ \x27<rect x="12" y="37" width="20" height="13" rx="2" fill="#141028" stroke="#3a3070" stroke-width="1"/>\x27+
4389
+ \x27<rect x="13" y="38" width="18" height="11" rx="1" fill="rgba(90,80,180,.35)"/>\x27+
4390
+ \x27<line x1="14" y1="41" x2="30" y2="41" stroke="#9090cc" stroke-width=".8" opacity=".8"/>\x27+
4391
+ \x27<line x1="14" y1="44" x2="28" y2="44" stroke="#7070aa" stroke-width=".8" opacity=".6"/>\x27+
4392
+ // Agent badge
4393
+ \x27<circle cx="22" cy="13" r="5" fill="#0f0f1e" stroke="\x27+shirtC+\x2780" stroke-width="1.2"/>\x27+
4394
+ \x27<text x="22" y="16" text-anchor="middle" font-size="6" font-family="system-ui">\x27+ico+\x27</text>\x27+
4395
+ \x27</svg>\x27;
4396
+ return \x27<div class="br-seat" id="brseat_\x27+safeLbl+\x27" data-lbl="\x27+esc(lbl)+\x27">\x27+
4397
+ \x27<div class="br-seat-box">\x27+
4398
+ \x27<div class="br-bubble" id="brbubble_\x27+safeLbl+\x27"></div>\x27+
4399
+ agentSvg+
4400
+ \x27<div class="br-seat-name" id="brname_\x27+safeLbl+\x27">\x27+esc(lbl)+\x27</div>\x27+
4401
+ \x27</div>\x27+
4402
+ \x27</div>\x27;
4403
+ }
4404
+
4405
+ // Arrange seats in a circle around center table
4406
+ // Positions computed from CSS: use CSS custom properties per seat index
4407
+ var seatsHtml = proposals.map(buildSeat).join(\x27\x27);
4408
+
4409
+ // Orchestrator at center (standing, prominent)
4410
+ var orchSvg = \x27<svg viewBox="0 0 54 70" width="54" height="70" xmlns="http://www.w3.org/2000/svg" font-family="system-ui,sans-serif">\x27+
4411
+ // Legs
4412
+ \x27<path d="M20 45 C19 54 18 62 17 66 C16 68 18 69 20 69 C22 69 23 68 23 65 C24 59 24 52 25 45 Z" fill="#252460"/>\x27+
4413
+ \x27<path d="M27 45 C28 54 29 62 30 66 C31 68 29 69 27 69 C25 69 24 68 24 65 C23 59 23 52 22 45 Z" fill="#252460"/>\x27+
4414
+ // Suit
4415
+ \x27<path d="M11 26 C10 24 13 21 22 19 C31 21 34 24 33 26 L34 45 L10 45 Z" fill="#252464"/>\x27+
4416
+ \x27<path d="M11 26 C10 24 13 21 22 19 L22 45 L10 45 Z" fill="#1e1d52"/>\x27+
4417
+ \x27<path d="M22 19 C31 21 34 24 33 26 L34 45 L22 45 Z" fill="#2a2870"/>\x27+
4418
+ // Tie
4419
+ \x27<path d="M22 22 L21 36 L22 40 L23 36 Z" fill="#818cf8"/>\x27+
4420
+ // Arms gesturing (spread wide — presenting)
4421
+ \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+
4422
+ \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+
4423
+ // Head
4424
+ \x27<circle cx="22" cy="13" r="9" fill="#fbbf24"/>\x27+
4425
+ \x27<circle cx="19" cy="12" r="1.5" fill="#0a0a14"/>\x27+
4426
+ \x27<circle cx="25" cy="12" r="1.5" fill="#0a0a14"/>\x27+
4427
+ \x27<circle cx="20" cy="11" r=".6" fill="rgba(255,255,255,.8)"/>\x27+
4428
+ \x27<circle cx="26" cy="11" r=".6" fill="rgba(255,255,255,.8)"/>\x27+
4429
+ // Mouth — speaking
4430
+ \x27<path d="M18 16 Q22 20 26 16" stroke="#8b4513" stroke-width="1.6" fill="none" stroke-linecap="round"/>\x27+
4431
+ // NHA badge
4432
+ \x27<circle cx="16" cy="30" r="3" fill="#0d0d1e" stroke="#818cf888" stroke-width="1"/>\x27+
4433
+ \x27<text x="16" y="32.5" text-anchor="middle" font-size="3.5" fill="#818cf8">N</text>\x27+
4434
+ // Crown / authority marker
4435
+ \x27<path d="M15 3 L17 8 L22 5 L27 8 L29 3 L22 0 Z" fill="#f59e0b"/>\x27+
4436
+ \x27<circle cx="17" cy="8" r="1.5" fill="#fbbf24"/>\x27+
4437
+ \x27<circle cx="22" cy="5" r="1.5" fill="#fbbf24"/>\x27+
4438
+ \x27<circle cx="27" cy="8" r="1.5" fill="#fbbf24"/>\x27+
4439
+ \x27</svg>\x27;
4440
+
4441
+ // Center table (SVG oval)
4442
+ var tableSvg = \x27<svg viewBox="0 0 160 80" width="160" height="80" xmlns="http://www.w3.org/2000/svg">\x27+
4443
+ // Table shadow
4444
+ \x27<ellipse cx="80" cy="44" rx="74" ry="34" fill="rgba(0,0,0,.3)"/>\x27+
4445
+ // Table surface — glossy dark wood
4446
+ \x27<ellipse cx="80" cy="40" rx="74" ry="34" fill="#1e1440" stroke="#3a2880" stroke-width="2"/>\x27+
4447
+ // Table shine
4448
+ \x27<ellipse cx="60" cy="28" rx="30" ry="12" fill="rgba(150,130,255,.08)"/>\x27+
4449
+ // NHA logo on table
4450
+ \x27<text x="80" y="46" text-anchor="middle" font-family="system-ui" font-size="18" font-weight="900" fill="rgba(100,90,200,.25)" letter-spacing="2">NHA</text>\x27+
4451
+ // Documents on table
4452
+ \x27<rect x="62" y="34" width="18" height="14" rx="2" fill="#141028" stroke="#4a3880" stroke-width="1" transform="rotate(-8 71 41)"/>\x27+
4453
+ \x27<rect x="82" y="36" width="18" height="14" rx="2" fill="#141028" stroke="#4a3880" stroke-width="1" transform="rotate(5 91 43)"/>\x27+
4454
+ \x27</svg>\x27;
4455
+
4456
+ var orchHtml = \x27<div class="br-orch" id="brOrch">\x27+
4457
+ \x27<div class="br-orch-speech" id="brOrchSpeech"></div>\x27+
4458
+ orchSvg+
4459
+ \x27<div class="br-orch-label">Orchestratore</div>\x27+
4460
+ \x27</div>\x27;
4461
+
4462
+ // Phase indicator + progress
4463
+ var headerHtml = \x27<div class="br-header">\x27+
4464
+ \x27<span class="br-phase-chip" id="brPhaseChip"></span>\x27+
4465
+ \x27<div class="br-progress-wrap" id="brProgressWrap"><div class="br-progress-bar" id="brProgressBar"></div></div>\x27+
4466
+ \x27</div>\x27;
4467
+
4468
+ var convergeHtml = \x27<div class="br-convergence" id="brConvergence" style="display:none"></div>\x27;
4469
+
4470
+ pb.innerHTML =
4471
+ \x27<div class="br-wrap">\x27+
4472
+ headerHtml+
4473
+ \x27<div class="br-room" style="--br-n:\x27+n+\x27">\x27+
4474
+ \x27<div class="br-table-center">\x27+tableSvg+orchHtml+\x27</div>\x27+
4475
+ \x27<div class="br-seats-ring" style="--br-n:\x27+n+\x27">\x27+seatsHtml+\x27</div>\x27+
4476
+ \x27</div>\x27+
4477
+ convergeHtml+
4478
+ \x27</div>\x27;
4479
+ }
4480
+
4481
+ // ── Update state (runs every call, including initial build) ──────────
4482
+
4483
+ // Phase chip
4484
+ var chipEl = document.getElementById(\x27brPhaseChip\x27);
4485
+ if (chipEl) { chipEl.textContent = phaseLabel; chipEl.style.setProperty(\x27--pc\x27, phaseColor); }
4360
4486
 
4487
+ // Progress bar
4488
+ var pbBar = document.getElementById(\x27brProgressBar\x27);
4489
+ if (pbBar) pbBar.style.width = progressPct + \x27%\x27;
4490
+ var pbWrap = document.getElementById(\x27brProgressWrap\x27);
4491
+ if (pbWrap) pbWrap.style.display = convergence != null ? \x27none\x27 : \x27\x27;
4492
+
4493
+ // Convergence
4494
+ var convEl = document.getElementById(\x27brConvergence\x27);
4495
+ if (convEl && convergence != null) {
4496
+ convEl.style.display = \x27block\x27;
4497
+ convEl.innerHTML = \x27<div class="br-conv-bar-outer"><div class="br-conv-bar-inner" style="width:\x27+Math.min(convergence,100)+\x27%"></div></div>\x27+
4498
+ \x27<div class="br-conv-text"><strong>\u2714 Convergenza \x27+convergence+\x27%</strong> \u2014 HERALD ha sintetizzato il consenso finale.</div>\x27;
4499
+ }
4500
+
4501
+ // Orchestrator speech bubble
4502
+ var orchSpeech = document.getElementById(\x27brOrchSpeech\x27);
4503
+ if (orchSpeech) {
4504
+ var orchSpeeches = {
4505
+ r1: [\x27Analizzate!\x27,\x27Al lavoro!\x27,\x27Forza!\x27,\x27Pensate!\x27],
4506
+ r2: [\x27Confrontate!\x27,\x27Leggete tutto!\x27,\x27Raffinare!\x27,\x27Scambiate!\x27],
4507
+ r3: [\x27Mediazione!\x27,\x27Convergete!\x27,\x27Trovate accordo!\x27],
4508
+ done: [\x27Ottimo!\x27,\x27Consenso!\x27,\x27Bene!\x27]
4509
+ };
4510
+ var spArr = orchSpeeches[phase] || orchSpeeches.r1;
4511
+ if (phase === \x27done\x27) {
4512
+ orchSpeech.style.display = \x27none\x27;
4513
+ } else {
4514
+ orchSpeech.style.display = \x27\x27;
4515
+ // Rotate through phrases based on progress
4516
+ orchSpeech.textContent = spArr[doneCount % spArr.length];
4517
+ orchSpeech.style.borderColor = phaseColor;
4518
+ orchSpeech.style.color = phaseColor;
4519
+ }
4520
+ }
4521
+
4522
+ // Orchestrator animation class
4523
+ var orchEl = document.getElementById(\x27brOrch\x27);
4524
+ if (orchEl) {
4525
+ orchEl.className = \x27br-orch\x27 + (phase===\x27done\x27 ? \x27 br-orch--done\x27 : \x27 br-orch--active\x27);
4526
+ orchEl.style.setProperty(\x27--oc\x27, phaseColor);
4527
+ }
4528
+
4529
+ // Update each agent seat state
4530
+ proposals.forEach(function(prop) {
4531
+ var lbl = prop.label || prop.agent;
4532
+ var safeLbl = lbl.replace(/[^a-zA-Z0-9_-]/g,\x27_\x27);
4533
+ var seatEl = document.getElementById(\x27brseat_\x27+safeLbl);
4534
+ var bubbleEl = document.getElementById(\x27brbubble_\x27+safeLbl);
4535
+ var nameEl = document.getElementById(\x27brname_\x27+safeLbl);
4536
+ var isDone = !!parlDoneAgents[lbl];
4537
+ var isActive = lbl === activeLabel;
4538
+
4539
+ if (seatEl) {
4540
+ seatEl.className = \x27br-seat\x27 +
4541
+ (isActive ? \x27 br-seat--active\x27 : \x27\x27) +
4542
+ (isDone ? \x27 br-seat--done\x27 : \x27\x27);
4543
+ seatEl.style.setProperty(\x27--sc\x27, phaseColor);
4544
+ }
4545
+ if (bubbleEl) {
4546
+ var actionStr2 = \x27\x27;
4547
+ if (phase===\x27r1\x27 && isActive) actionStr2 = \x27...analizza\x27;
4548
+ else if (phase===\x27r1\x27 && isDone) actionStr2 = \x27\u2714 bozza pronta\x27;
4549
+ else if (phase===\x27r2\x27 && isActive) actionStr2 = \x27...legge + raffina\x27;
4550
+ else if (phase===\x27r2\x27 && isDone) actionStr2 = \x27\u2714 raffinato\x27;
4551
+ else if (phase===\x27r3\x27 && isActive) actionStr2 = \x27...media\x27;
4552
+ else if (phase===\x27done\x27) actionStr2 = \x27\u2714 consenso\x27;
4553
+ else if (!isActive && !isDone) actionStr2 = \x27in attesa\x27;
4554
+ bubbleEl.textContent = actionStr2;
4555
+ bubbleEl.style.display = actionStr2 ? \x27\x27 : \x27none\x27;
4556
+ bubbleEl.style.borderColor = isActive ? phaseColor : (isDone ? \x27#22c55e\x27 : \x27#3a3060\x27);
4557
+ bubbleEl.style.color = isActive ? phaseColor : (isDone ? \x27#4ade80\x27 : \x27#6b7280\x27);
4558
+ }
4559
+ if (nameEl) {
4560
+ nameEl.style.color = isDone ? \x27#4ade80\x27 : (isActive ? phaseColor : \x27#8880aa\x27);
4561
+ }
4562
+ });
4563
+
4564
+ // ── Old function stubs needed by remaining code paths ────────────────
4361
4565
  function buildChar(prop, isDone, isActive, isOrchestratorTarget) {
4362
4566
  var lbl = prop.label || prop.agent;
4363
4567
  var ico = prop.icon || String.fromCharCode(9632);
@@ -4767,36 +4971,6 @@ async function runStudio() {
4767
4971
  flyingDocHtml += \x27</div>\x27;
4768
4972
  }
4769
4973
 
4770
- // ── Assemble agent desks row ──────────────────────────────────────
4771
- var desksHtml = proposals.map(function(prop) {
4772
- var lbl = prop.label || prop.agent;
4773
- return buildChar(prop, !!parlDoneAgents[lbl], lbl===activeLabel, false);
4774
- }).join(\x27\x27);
4775
-
4776
- var convergenceHtml = convergence != null
4777
- ? (\x27<div class="prl-conv-wrap"><div class="prl-conv-bar-outer"><div class="prl-conv-bar-inner" style="width:\x27+Math.min(convergence,100)+\x27%"></div></div>\x27+
4778
- \x27<div class="prl-conv-text"><strong>\u2714 Convergenza \x27+convergence+\x27%</strong> &mdash; le analisi condividono il \x27+convergence+\x27% dei concetti chiave (Jaccard). HERALD ha sintetizzato il consenso finale.</div></div>\x27)
4779
- : (\x27<div class="prl-progress"><div class="prl-progress__bar" style="width:\x27+progressPct+\x27%"></div></div>\x27);
4780
-
4781
- pb.innerHTML =
4782
- \x27<div class="prl-wrap">\x27+
4783
- \x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor+\x27">\x27+phaseLabel+\x27</span></div>\x27+
4784
- \x27<div class="prl-office">\x27+
4785
- officeRoomDecor()+
4786
- \x27<div class="prl-office-floor"></div>\x27+
4787
- \x27<div class="prl-desks-row" style="position:relative;z-index:2">\x27+desksHtml+\x27</div>\x27+
4788
- masterHtml+
4789
- flyingDocHtml+
4790
- \x27</div>\x27+
4791
- convergenceHtml+
4792
- \x27</div>\x27;
4793
-
4794
- // Force Safari compositing repaint
4795
- void pb.offsetHeight;
4796
- requestAnimationFrame(function(){
4797
- pb.style.opacity = \x270.99\x27;
4798
- requestAnimationFrame(function(){ pb.style.opacity = \x271\x27; });
4799
- });
4800
4974
  }
4801
4975
 
4802
4976
  // Show initial R1 block and scroll into view
@@ -5191,10 +5365,33 @@ function runStudioStep(idx, node, task, context, stepDef, signal) {
5191
5365
  tb.textContent = st;
5192
5366
  }
5193
5367
  } else {
5194
- // Live token counter shows progress without raw content
5195
- var chars = output.length;
5196
- var toks = Math.ceil(chars / 4);
5197
- tb.innerHTML = \x27<span style="color:var(--green);font-family:var(--mono);font-size:10px">&#9679; Generating\u2026 \x27 + toks + \x27 token</span>\x27;
5368
+ // Word-by-word streaming text with blinking cursor
5369
+ var snippet = output.length > 400 ? output.slice(-400) : output;
5370
+ var safeSnip = snippet.replace(/&/g,\x27&amp;\x27).replace(/</g,\x27&lt;\x27).replace(/>/g,\x27&gt;\x27);
5371
+ tb.innerHTML = \x27<span style="font-size:11px;color:var(--text);line-height:1.5;white-space:pre-wrap;word-break:break-word;font-family:var(--font)">\x27 + safeSnip + \x27<span class="stream-cursor" style="display:inline-block;width:2px;height:13px;background:var(--green);margin-left:1px;vertical-align:text-bottom;animation:streamBlink .7s step-end infinite">&#8203;</span></span>\x27;
5372
+ // Update thought bubble of the currently active workflow desk
5373
+ var activeDeskEl = document.querySelector(\x27.prl-desk--active[data-agent-label]\x27);
5374
+ if (activeDeskEl) {
5375
+ var wfBubble = activeDeskEl.querySelector(\x27.prl-action-bubble--active\x27);
5376
+ if (wfBubble) {
5377
+ var wfRaw = output.length > 42 ? output.slice(-42) : output;
5378
+ var wfSafe = wfRaw.replace(/&/g,\x27&amp;\x27).replace(/</g,\x27&lt;\x27).replace(/>/g,\x27&gt;\x27);
5379
+ wfBubble.style.maxWidth = \x2796px\x27;
5380
+ wfBubble.style.fontSize = \x278px\x27;
5381
+ wfBubble.innerHTML = wfSafe + \x27<span style="display:inline-block;width:2px;height:9px;background:var(--green);margin-left:1px;vertical-align:text-bottom;animation:streamBlink .7s step-end infinite">&#8203;</span>\x27;
5382
+ }
5383
+ }
5384
+ // Update thought bubble of the active boardroom seat
5385
+ if (parlActiveAgent) {
5386
+ var brSafeLbl = parlActiveAgent.replace(new RegExp(\x27[^a-zA-Z0-9_-]\x27,\x27g\x27),\x27_\x27);
5387
+ var brBubbleEl = document.getElementById(\x27brbubble_\x27+brSafeLbl);
5388
+ if (brBubbleEl) {
5389
+ var brRaw = output.length > 42 ? output.slice(-42) : output;
5390
+ var brSafe = brRaw.replace(/&/g,\x27&amp;\x27).replace(/</g,\x27&lt;\x27).replace(/>/g,\x27&gt;\x27);
5391
+ brBubbleEl.style.display = \x27\x27;
5392
+ 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">&#8203;</span>\x27;
5393
+ }
5394
+ }
5198
5395
  }
5199
5396
  }
5200
5397
  }
@@ -5951,7 +6148,68 @@ input:focus,textarea:focus{border-color:var(--green3)}
5951
6148
  .wf-sbraita-bubble{position:absolute;top:-28px;left:50%;transform:translateX(-50%);background:#1a0a0a;border:1.5px solid #ef4444;color:#fca5a5;font-family:var(--mono);font-size:9px;font-weight:800;padding:3px 8px;border-radius:8px;white-space:nowrap;letter-spacing:.5px;animation:sbraitaPop .4s ease-in-out infinite alternate;pointer-events:none;z-index:4}
5952
6149
  .wf-sbraita-bubble::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#ef4444}
5953
6150
  @keyframes sbraitaPop{0%{transform:translateX(-50%) scale(1) rotate(-2deg)}100%{transform:translateX(-50%) scale(1.06) rotate(2deg)}}
5954
- /* ── Parliament Office Cartoon ── */
6151
+ /* ── Parliament Boardroom 3D ── */
6152
+ /* Outer wrapper */
6153
+ .br-wrap{background:#090714;border:1.5px solid #6366f1;border-radius:14px;padding:12px 14px;margin-bottom:16px;animation:stNodeIn .35s ease forwards;overflow:hidden}
6154
+ /* Header: phase chip + progress */
6155
+ .br-header{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}
6156
+ .br-phase-chip{font-size:10px;font-weight:800;font-family:var(--mono);letter-spacing:.3px;color:var(--pc,#6366f1);background:rgba(99,102,241,.12);border:1px solid var(--pc,rgba(99,102,241,.4));border-radius:20px;padding:3px 12px;display:inline-block;transition:color .4s,border-color .4s}
6157
+ .br-progress-wrap{flex:1;height:3px;background:#1a1630;border-radius:4px;overflow:hidden;min-width:60px}
6158
+ .br-progress-bar{height:100%;background:linear-gradient(90deg,#6366f1,#22d3ee);border-radius:4px;transition:width .5s ease;width:0%}
6159
+ /* Boardroom 3D scene */
6160
+ .br-room{position:relative;min-height:220px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:10px 8px 16px;
6161
+ background:linear-gradient(180deg,#141030 0%,#1c1848 50%,#141030 100%);
6162
+ border-radius:10px;overflow:hidden}
6163
+ /* Ambient ceiling glow */
6164
+ .br-room::before{content:"";position:absolute;inset:0;background:
6165
+ radial-gradient(ellipse 70% 50% at 50% 5%,rgba(180,160,255,.2) 0%,transparent 70%),
6166
+ radial-gradient(ellipse 30% 30% at 50% 0%,rgba(255,220,100,.12) 0%,transparent 60%);pointer-events:none}
6167
+ /* Floor perspective */
6168
+ .br-room::after{content:"";position:absolute;bottom:0;left:0;right:0;height:40px;
6169
+ background:linear-gradient(180deg,transparent 0%,rgba(100,80,200,.08) 50%,rgba(60,40,120,.25) 100%);
6170
+ border-top:1px solid rgba(100,80,200,.15);pointer-events:none}
6171
+ /* Center: table + orchestrator */
6172
+ .br-table-center{position:relative;display:flex;flex-direction:column;align-items:center;gap:0;z-index:3}
6173
+ /* Orchestrator standing at head of table */
6174
+ .br-orch{display:flex;flex-direction:column;align-items:center;gap:2px;z-index:4;position:relative}
6175
+ .br-orch--active .br-orch-arm-l{transform-origin:50% 0%;animation:brOrchArmL 2s ease-in-out infinite}
6176
+ .br-orch--active .br-orch-arm-r{transform-origin:50% 0%;animation:brOrchArmR 2.4s ease-in-out infinite}
6177
+ @keyframes brOrchArmL{0%,100%{transform:rotate(0deg)}40%{transform:rotate(-22deg)}70%{transform:rotate(-10deg)}}
6178
+ @keyframes brOrchArmR{0%,100%{transform:rotate(0deg)}30%{transform:rotate(18deg)}65%{transform:rotate(8deg)}}
6179
+ .br-orch--done{filter:drop-shadow(0 0 12px #22c55eaa)}
6180
+ .br-orch-speech{position:absolute;top:-28px;left:50%;transform:translateX(-50%);
6181
+ font-size:9px;font-weight:800;font-family:var(--mono);letter-spacing:.4px;
6182
+ padding:3px 8px;border:1.5px solid #6366f1;border-radius:8px;
6183
+ background:#0d0a1e;white-space:nowrap;
6184
+ animation:brSpeechPop .6s ease-in-out infinite alternate;z-index:5;pointer-events:none}
6185
+ @keyframes brSpeechPop{0%{transform:translateX(-50%) scale(1) rotate(-1deg)}100%{transform:translateX(-50%) scale(1.05) rotate(1deg)}}
6186
+ .br-orch-speech::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:4px solid transparent;border-top-color:#6366f1}
6187
+ .br-orch-label{font-size:8px;font-family:var(--mono);font-weight:800;color:#818cf8;text-align:center;letter-spacing:.5px}
6188
+ /* Seats ring around table */
6189
+ .br-seats-ring{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;z-index:2;padding:4px 0;width:100%}
6190
+ /* Individual seat / cubicle */
6191
+ .br-seat{display:flex;flex-direction:column;align-items:center;gap:0;transition:transform .3s}
6192
+ .br-seat-box{display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px 8px 6px;border-radius:12px;
6193
+ background:#1a1535;border:1.5px solid #3a3060;
6194
+ box-shadow:0 2px 10px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.06);
6195
+ transition:border-color .3s,background .3s,box-shadow .3s;position:relative;min-width:70px}
6196
+ .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
+ .br-seat--active{transform:scale(1.04)}
6198
+ .br-seat--done .br-seat-box{background:#162516;border-color:#2a4a2a}
6199
+ /* Action bubble above agent */
6200
+ .br-bubble{font-size:9px;font-family:var(--mono);padding:2px 7px;border-radius:7px;border:1px solid #3a3060;background:#0d0a1e;min-height:14px;text-align:center;line-height:1.4;transition:all .3s;word-break:break-word;max-width:90px}
6201
+ /* Agent name */
6202
+ .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
+ /* SVG arm animations when agent is active (typing) */
6204
+ .br-seat--active .br-arm-l{transform-origin:50% 100%;animation:brArmType .7s ease-in-out infinite}
6205
+ .br-seat--active .br-arm-r{transform-origin:50% 100%;animation:brArmType .7s ease-in-out infinite reverse}
6206
+ @keyframes brArmType{0%,100%{transform:rotate(-6deg) translateY(0)}50%{transform:rotate(6deg) translateY(2px)}}
6207
+ /* Convergence */
6208
+ .br-convergence{margin-top:10px;padding:8px 12px;background:rgba(34,197,94,.06);border:1px solid rgba(34,197,94,.22);border-radius:8px}
6209
+ .br-conv-bar-outer{height:4px;background:#1a2e1a;border-radius:4px;overflow:hidden;margin-bottom:6px}
6210
+ .br-conv-bar-inner{height:100%;background:linear-gradient(90deg,#22c55e,#4ade80);border-radius:4px;transition:width .8s ease}
6211
+ .br-conv-text{font-size:9px;color:#86efac;line-height:1.55}
6212
+ /* Keep old prl-* classes for workflow (not touched) */
5955
6213
  .prl-wrap{background:#0b0918;border:1.5px solid #6366f1;border-radius:14px;padding:14px 16px 12px;margin-bottom:16px;animation:stNodeIn .35s ease forwards;overflow:hidden}
5956
6214
  @keyframes parlPulse{0%,100%{border-color:#6366f1;box-shadow:none}50%{border-color:#818cf8;box-shadow:0 0 20px rgba(99,102,241,.3)}}
5957
6215
  .prl-header{display:flex;align-items:center;margin-bottom:10px}
@@ -6008,6 +6266,7 @@ input:focus,textarea:focus{border-color:var(--green3)}
6008
6266
  .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}
6009
6267
  .prl-action-bubble--active{color:var(--dc,#6366f1);border-color:var(--dc,#6366f1);background:rgba(99,102,241,.08);animation:parlBubblePop .4s ease}
6010
6268
  @keyframes parlBubblePop{0%{transform:scale(.85);opacity:.5}100%{transform:scale(1);opacity:1}}
6269
+ @keyframes streamBlink{0%,100%{opacity:1}50%{opacity:0}}
6011
6270
  /* Character SVG animations */
6012
6271
  @keyframes parlArmType{0%,100%{transform:rotate(-8deg) translateY(0)}50%{transform:rotate(8deg) translateY(2px)}}
6013
6272
  @keyframes parlHeadNod{0%,100%{transform:translateY(0) rotate(0deg)}50%{transform:translateY(2px) rotate(4deg)}}