From f83ea9d90ae974c5de1b12f0c8d6f4668d9819ea Mon Sep 17 00:00:00 2001 From: jaakko Date: Fri, 3 Apr 2026 12:38:45 +0300 Subject: [PATCH] =?UTF-8?q?Puhuvat=20p=C3=A4=C3=A4t=20agenteille:=20!=20ja?= =?UTF-8?q?=20puhekupla=20vuorovaikutuksen=20lis=C3=A4=C3=A4miseksi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- network-poc/hub/nodes.db | Bin 40960 -> 73728 bytes network-poc/static/avatars/README.md | 34 ++ network-poc/static/avatars/forge_hero.svg | 44 --- network-poc/static/avatars/lizard_ai.svg | 54 --- network-poc/static/avatars/raccoon_ai.svg | 66 ---- network-poc/static/avatars/sloth_ai.svg | 49 --- network-poc/static/index.html | 384 ++++++++++++++++++---- 7 files changed, 353 insertions(+), 278 deletions(-) create mode 100644 network-poc/static/avatars/README.md delete mode 100644 network-poc/static/avatars/forge_hero.svg delete mode 100644 network-poc/static/avatars/lizard_ai.svg delete mode 100644 network-poc/static/avatars/raccoon_ai.svg delete mode 100644 network-poc/static/avatars/sloth_ai.svg diff --git a/network-poc/hub/nodes.db b/network-poc/hub/nodes.db index 7cf2122f965f7a68802657f9c148597407e23a7a..e6efe86814ed9cdb1c779fd6a06fc886582fd123 100644 GIT binary patch delta 11906 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 delta 206 zcmZoTz|wGlX@V3R(<}xC2Cj(;c1%pOHYO~T=LT|__-`}tzvaKZShu;3|62)Ec|bPBm)=!Z~kxmANk*K zU*opnTEwNpIf>&3M - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/network-poc/static/avatars/lizard_ai.svg b/network-poc/static/avatars/lizard_ai.svg deleted file mode 100644 index 43d1cba..0000000 --- a/network-poc/static/avatars/lizard_ai.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { - } - </> - - diff --git a/network-poc/static/avatars/raccoon_ai.svg b/network-poc/static/avatars/raccoon_ai.svg deleted file mode 100644 index 5e9d292..0000000 --- a/network-poc/static/avatars/raccoon_ai.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/network-poc/static/avatars/sloth_ai.svg b/network-poc/static/avatars/sloth_ai.svg deleted file mode 100644 index 1194b47..0000000 --- a/network-poc/static/avatars/sloth_ai.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Z - z - z - - - - - - - - - diff --git a/network-poc/static/index.html b/network-poc/static/index.html index 3747a83..ffd3030 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -393,6 +393,7 @@ align-items: center; margin-bottom: 40px; perspective: 1000px; + padding: 25px 50px; } .org-level { display: flex; @@ -439,6 +440,18 @@ border-color: rgba(240, 246, 252, 0.3); box-shadow: 0 12px 20px rgba(0,0,0,0.4); } + @keyframes idle-breathe { + 0%, 100% { transform: translateY(0) scale(1); } + 50% { transform: translateY(-2px) scale(1.01); } + } + @keyframes talking-head { + 0% { transform: scale(1.05) scaleY(1) translateY(0); } + 25% { transform: scale(1.05) scaleY(0.96) scaleX(1.02) translateY(2px); } + 50% { transform: scale(1.05) scaleY(1.02) scaleX(0.98) translateY(-2px); } + 75% { transform: scale(1.05) scaleY(0.97) scaleX(1.01) translateY(1px); } + 100% { transform: scale(1.05) scaleY(1) translateY(0); } + } + .avatar-card img { width: 80px; height: 80px; @@ -448,7 +461,10 @@ transition: all 0.4s ease; object-fit: cover; background: #010409; + animation: idle-breathe 4s infinite ease-in-out; + transform-origin: bottom center; } + .avatar-card.active, .avatar-card.selected { opacity: 1; transform: translateY(-8px) scale(1.05); @@ -457,10 +473,134 @@ box-shadow: 0 16px 24px rgba(0,0,0,0.5), 0 0 20px rgba(88, 166, 255, 0.3); z-index: 2; } - .avatar-card.active img, .avatar-card.selected img { + + .avatar-card.selected img { border-color: var(--accent-color); box-shadow: 0 0 25px rgba(88, 166, 255, 0.5); transform: scale(1.05); + animation: none; + } + + .avatar-card.active img { + border-color: var(--accent-color); + box-shadow: 0 0 25px rgba(88, 166, 255, 0.8); + animation: talking-head 0.4s infinite ease-in-out; + transform-origin: bottom center; + } + @keyframes talking-head-gallery { + 0% { transform: scaleY(1) translateY(0); } + 25% { transform: scaleY(0.94) scaleX(1.04) translateY(3px); } + 50% { transform: scaleY(1.04) scaleX(0.96) translateY(-3px); } + 75% { transform: scaleY(0.96) scaleX(1.02) translateY(1px); } + 100% { transform: scaleY(1) translateY(0); } + } + .gallery-head { + width: 55px; + height: 55px; + border-radius: 12px; + border: 2px solid rgba(240, 246, 252, 0.1); + object-fit: cover; + background: #010409; + transition: all 0.3s ease; + opacity: 0.4; + filter: grayscale(80%); + } + .gallery-head.active { + opacity: 1; + filter: grayscale(0%); + border-color: var(--accent-color); + box-shadow: 0 0 15px rgba(88, 166, 255, 0.5); + animation: talking-head-gallery 0.4s infinite ease-in-out; + transform-origin: bottom center; + } + + @keyframes confused-shake { + 0% { transform: translateX(0); } + 25% { transform: translateX(-2px) rotate(-3deg); } + 50% { transform: translateX(0); } + 75% { transform: translateX(2px) rotate(3deg); } + 100% { transform: translateX(0); } + } + + .gallery-head-wrap[data-tooltip]::before { + content: attr(data-tooltip); + position: absolute; + bottom: 110%; + left: 50%; + transform: translateX(-50%); + background: rgba(13, 17, 23, 0.95); + color: #f0f6fc; + padding: 8px 12px; + border-radius: 6px; + font-size: 11px; + white-space: pre-wrap; + width: 140px; + text-align: left; + border: 1px solid var(--border-color); + z-index: 100; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s; + box-shadow: 0 4px 12px rgba(0,0,0,0.5); + } + .gallery-head-wrap:hover[data-tooltip]:not([data-tooltip=""])::before { opacity: 1; } + + /* Yhteiset kuplasäännöt */ + .gallery-head-wrap.state-question::after, + .gallery-head-wrap.state-alert::after, + .gallery-head-wrap.active:not(.state-question):not(.state-alert)::after { + position: absolute; + top: -10px; + right: -10px; + font-size: 14px; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + z-index: 10; + } + + /* State: Kysymys (Sininen ?) */ + .gallery-head-wrap.state-question::after { + content: '?'; + color: #ffffff; + font-weight: 900; + font-family: system-ui, -apple-system, sans-serif; + animation: speech-pulse 1s infinite alternate; + background: #1f6feb; border: 1px solid #58a6ff; + } + .gallery-head.state-question { + border-color: #58a6ff; box-shadow: 0 0 15px rgba(88, 166, 255, 0.4); + animation: confused-shake 2s infinite ease-in-out; filter: grayscale(10%); opacity: 0.9; + } + + /* State: Alert (Punainen !) */ + .gallery-head-wrap.state-alert::after { + content: '!'; + color: #ffffff; + font-weight: 900; + font-family: system-ui, -apple-system, sans-serif; + animation: speech-pulse 0.5s infinite alternate; + background: #da3633; border: 1px solid #ff7b72; + } + .gallery-head.state-alert { + border-color: #ff4444; box-shadow: 0 0 15px rgba(255, 68, 68, 0.5); + animation: confused-shake 0.5s infinite; filter: grayscale(30%); opacity: 0.9; + } + + .gallery-head-wrap { position: relative; display: inline-block; cursor: help; } + @keyframes speech-pulse { + 0% { transform: scale(0.8) translateY(0); opacity: 0.6; } + 50% { transform: scale(1.1) translateY(-2px); opacity: 1; } + 100% { transform: scale(0.8) translateY(0); opacity: 0.6; } + } + .gallery-head-wrap.active:not(.state-question):not(.state-alert)::after { + content: '💬'; + animation: speech-pulse 0.8s infinite ease-in-out; + background: #0d1117; + border: 1px solid var(--accent-color); } .avatar-name { font-weight: 700; font-size: 13px; color: #f0f6fc; letter-spacing: 0.5px; margin-bottom: 2px; } .avatar-role { font-size: 10px; color: #8b949e; text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600; line-height: 1.2; word-wrap: break-word; } @@ -523,7 +663,7 @@ #metrics-grid { grid-template-columns: 1fr 1fr !important; } /* Org chart mobile tweaks */ - .org-chart { padding-left: 0; padding-right: 0; } + .org-chart { padding: 20px 10px; } .org-branch { display: none; } .org-connector { margin-bottom: 10px; height: 20px; } .org-level { flex-wrap: wrap; justify-content: center; gap: 15px !important; } @@ -859,75 +999,96 @@ Monitoring Active -
- -
-
- Asiakas (Kettu) -
Asiakas
-
Tuoteomistaja
+
+ +
+
+ +
+
+ Asiakas (Kettu) +
Asiakas
+
Tuoteomistaja
+
+
+ +
+ + +
+ +
+ Tarkkailija (Aikuinen Susi) +
Tarkkailija
+
Laadunvalvonta
+
+ +
+ Manageri (Karhunpentu) +
Manageri
+
KPN CLI
+
+
+ +
+ +
+ + +
+
+ Koodari (Salamanteri) +
Koodari
+
SOFTAKEHITYS
+
+
+ Data-Agentti (Pesukarhu) +
Data
+
Tietokannat
+
+
+ QA (Pikkususi) +
QA
+
Testaus
+
+
+ DevOps (Laiskiainen) +
DevOps
+
Käyttöönotto
+
+
+
+ + +
+
+ + Tallennettu +
+ +
- -
- - -
- -
- Tarkkailija (Aikuinen Susi) -
Tarkkailija
-
Laadunvalvonta
-
- -
- Manageri (Karhunpentu) -
Manageri
-
KPN CLI
-
-
- -
- -
- - -
-
- Koodari (Salamanteri) -
Koodari
-
Ohjelmistokehitys
-
-
- Data-Agentti (Pesukarhu) -
Data
-
Tietokannat
-
-
- QA (Pikkususi) -
QA
-
Testaus
-
-
- DevOps (Laiskiainen) -
DevOps
-
Käyttöönotto
+ + +
+
+
-
-
- - Tallennettu -
- - -
- -
+
$ kpn hub connect wss://localhost
✓ Yhdistetty Kipinä Hubiin
@@ -981,6 +1142,32 @@ } } + // Piilotettu ominaisuus: Puhuvien videoiden / gif-animaatioiden kytkentä + // Aseta true kun olet luonut _puhuva.gif tiedostot /avatars -kansioon + window.USE_ANIMATED_GIFS = false; + + // Update gallery heads + document.querySelectorAll('.gallery-head').forEach(el => { + el.classList.remove('active'); + if (window.USE_ANIMATED_GIFS) { + el.src = el.src.replace('_puhuva.gif', '.png'); + } + }); + document.querySelectorAll('.gallery-head-wrap').forEach(el => el.classList.remove('active')); + selectedAgents.forEach(agent => { + const gel = document.getElementById('gallery-' + agent); + const wrap = document.getElementById('wrap-' + agent); + if (gel) { + gel.classList.add('active'); + if (window.USE_ANIMATED_GIFS) { + gel.src = gel.src.replace('.png', '_puhuva.gif'); + } + } + if (wrap) wrap.classList.add('active'); + }); + + checkAgentConfusion(); + if (selectedAgents.size === 0) { editor.classList.remove('visible'); return; @@ -988,6 +1175,9 @@ editor.classList.add('visible'); + + + if (selectedAgents.size === 1) { const agent = [...selectedAgents][0]; const cfg = agentPrompts[agent]; @@ -1062,10 +1252,74 @@ localStorage.setItem('kpn-shared-prompt', e.target.value); } + checkAgentConfusion(); + saved.style.opacity = '1'; clearTimeout(saved._t); saved._t = setTimeout(() => saved.style.opacity = '0', 1500); }); + + function checkAgentConfusion() { + Object.keys(agentPrompts).forEach(agent => { + const prompt = agentPrompts[agent].prompt || ""; + const wrap = document.getElementById('wrap-' + agent); + const gel = document.getElementById('gallery-' + agent); + if (!wrap || !gel) return; + + // Nollataan tilat + wrap.classList.remove('state-question', 'state-alert'); + gel.classList.remove('state-question', 'state-alert'); + wrap.removeAttribute('data-tooltip'); + + const pLow = prompt.toLowerCase(); + const agentTitle = (agentPrompts[agent].name.split(' — ')[0] || "AGENTTI").toUpperCase(); + + // Hälytys / Virhe + if (pLow.includes('todo') || pLow.includes('viallinen') || pLow.includes('virhe')) { + wrap.classList.add('state-alert'); + gel.classList.add('state-alert'); + wrap.setAttribute('data-tooltip', `❗ ${agentTitle}: "Kriittinen virhe ohjeistuksessa!"\n(Koodissa tai promptissa esiintyy teksti TODO, viallinen tai virhe. Korjaa ohje välittömästi.)`); + } + // Kysyttävää / Hämmennys + else if (prompt.trim().length <= 15 || prompt.includes('?')) { + wrap.classList.add('state-question'); + gel.classList.add('state-question'); + + const questions = { + client: 'Millaisia uusia ominaisuuksia tuotteessa pitäisi olla?', + manager: 'Kuka asiantuntijoista ottaa vastuulleen tämän taskin?', + coder: 'Käytetäänkö tässä komponentissa uusinta React-ohjetta?', + data: 'Millainen tietorakenne käyttäjästä tallennetaan kantaan?', + qa: 'Onko tälle koodille olemassa jo kattavat yksikkötestit?', + tester: 'Mihin haluaisit julkaista tämän laiteympäristön version?', + observer: 'Mitä laatumetriikkoja minun tulisi ensisijaisesti painottaa?' + }; + const exampleQ = questions[agent] || 'Mitä minun pitäisi tehdä seuraavaksi?'; + + const reason = prompt.trim().length <= 15 ? 'Määrittely on tällä hetkellä liian lyhyt.' : 'Ohje on jätetty avoimeksi (? -merkki).'; + wrap.setAttribute('data-tooltip', `❓ ${agentTitle}: "${exampleQ}"\n\n(Agentti odottaa päätöstäsi: ${reason})`); + } + // Normaali keskustelu aktiivisena + else if (selectedAgents.has(agent)) { + // Haetaan satunnainen "toinen agentti", johon viitata + // Tehdään tästä deterministinen agentin nimen perusteella, ettei vilku + const targets = { + client: 'Managerin', + manager: 'Asiakkaan', + coder: 'DevOpsin', + data: 'Koodarin', + qa: 'Data-Agentin', + tester: 'QA:n', + observer: 'Managerin' + }; + const targetName = targets[agent] || 'Koodarin'; + wrap.setAttribute('data-tooltip', `💬 ${agentTitle}: "Hei, minäkin haluan osallistua!\nVoisin tehdä ${targetName} asiaan tällaisen toiminnallisuuden!"`); + } + }); + } + + // Tarkistetaan heti alussa + setTimeout(checkAgentConfusion, 100); window.switchMainTab = function(tab) { document.querySelectorAll('.main-panel').forEach(p => p.classList.remove('active'));