c5ea8cbb63
Make A2A togglable, keep reply context while reading, route agent data to //10.4.7.11/share/Agents, and polish themes plus export-intel sync cancel.
127 lines
8.1 KiB
JavaScript
127 lines
8.1 KiB
JavaScript
/** Agent avatars — bright cool cyan/blue team look (readable on dark UI) */
|
|
window.AgentAvatars = (function () {
|
|
var CFG = {
|
|
herman: { hoodie: '#1d4ed8', hair: '#5b3a29', skin: '#f0c9a8', style: 'exec', accent: '#fbbf24' },
|
|
marketing: { hoodie: '#0891b2', hair: '#1f2937', skin: '#f5d0b0', style: 'bob', accent: '#22d3ee' },
|
|
bizdev: { hoodie: '#0284c7', hair: '#3d2314', skin: '#e8c4a0', style: 'short', accent: '#38bdf8' },
|
|
finance: { hoodie: '#0d9488', hair: '#3d2314', skin: '#f0c9a8', style: 'glasses', accent: '#2dd4bf' },
|
|
sourcing: { hoodie: '#0369a1', hair: '#1a1a1a', skin: '#e0b890', style: 'short', accent: '#7dd3fc' },
|
|
product: { hoodie: '#4f46e5', hair: '#5b3a29', skin: '#f5d0b0', style: 'curl', accent: '#818cf8' },
|
|
halal: { hoodie: '#059669', hair: '#1f2937', skin: '#e8c4a0', style: 'short', accent: '#34d399' },
|
|
design: { hoodie: '#0e7490', hair: '#111827', skin: '#f5d0b0', style: 'long', accent: '#67e8f9' },
|
|
knowledge: { hoodie: '#4338ca', hair: '#374151', skin: '#f0c9a8', style: 'glasses', accent: '#a5b4fc' },
|
|
retail: { hoodie: '#0f766e', hair: '#3d2314', skin: '#e8c4a0', style: 'short', accent: '#5eead4' },
|
|
browser: { hoodie: '#2563eb', hair: '#1f2937', skin: '#e0b890', style: 'short', accent: '#60a5fa' },
|
|
hr: { hoodie: '#6366f1', hair: '#3d2314', skin: '#e8c4a0', style: 'bob', accent: '#c7d2fe' },
|
|
email: { hoodie: '#475569', hair: '#5b3a29', skin: '#e8c4a0', style: 'short', accent: '#94a3b8' },
|
|
research: { hoodie: '#0f766e', hair: '#1a1a1a', skin: '#f5d0b0', style: 'glasses', accent: '#2dd4bf' },
|
|
sysops: { hoodie: '#1e40af', hair: '#5b3a29', skin: '#f0c9a8', style: 'short', accent: '#38bdf8', hat: 'cap' },
|
|
packaging: { hoodie: '#1d4ed8', hair: '#3d2314', skin: '#e0b890', style: 'short', accent: '#93c5fd' },
|
|
webbuilder: { hoodie: '#0284c7', hair: '#1f2937', skin: '#e8c4a0', style: 'glasses', accent: '#38bdf8', hat: 'cap' },
|
|
};
|
|
|
|
function cfg(key, fallbackColor) {
|
|
var k = (key || 'agent').toLowerCase();
|
|
var c = CFG[k] || { hoodie: fallbackColor || '#0284c7', hair: '#3d2314', skin: '#f0c9a8', style: 'short', accent: '#38bdf8' };
|
|
return c;
|
|
}
|
|
|
|
function lighten(hex, amt) {
|
|
hex = (hex || '#0284c7').replace('#', '');
|
|
if (hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
|
|
var n = parseInt(hex, 16);
|
|
var r = Math.min(255, ((n >> 16) & 255) + amt);
|
|
var g = Math.min(255, ((n >> 8) & 255) + amt);
|
|
var b = Math.min(255, (n & 255) + amt);
|
|
return '#' + (0x1000000 + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
}
|
|
|
|
function capSvg(hid, c) {
|
|
return (
|
|
'<path d="M22,44 Q50,30 78,44 L82,48 Q50,54 18,48Z" fill="#0f172a" opacity="0.2"/>' +
|
|
'<ellipse cx="50" cy="36" rx="26" ry="12" fill="' + lighten(c.hoodie, 40) + '"/>' +
|
|
'<path d="M24,40 Q50,26 76,40 L88,46 Q50,52 14,46Z" fill="' + c.hoodie + '"/>' +
|
|
'<path d="M26,38 Q50,28 74,38" fill="none" stroke="' + c.accent + '" stroke-width="1.4" opacity="0.7"/>' +
|
|
'<rect x="46" y="28" width="8" height="5" rx="1" fill="' + c.accent + '"/>'
|
|
);
|
|
}
|
|
|
|
function hairPath(style) {
|
|
if (style === 'long') return 'M28,38 Q20,18 40,14 Q60,10 72,22 Q78,32 74,48 Q70,56 62,52 Q58,38 50,36 Q42,36 38,48 Q32,52 28,38Z';
|
|
if (style === 'bob') return 'M26,40 Q24,22 42,16 Q62,14 74,28 Q76,42 70,50 Q50,54 30,48 Q24,44 26,40Z';
|
|
if (style === 'curl') return 'M28,42 Q22,24 38,16 Q52,12 68,20 Q76,30 72,44 Q66,52 54,48 Q44,52 34,46 Q26,44 28,42Z';
|
|
return 'M30,40 Q28,24 44,18 Q58,16 70,26 Q74,36 70,44 Q54,48 38,44 Q30,42 30,40Z';
|
|
}
|
|
|
|
function svgAvatar(key, color) {
|
|
var c = cfg(key, color);
|
|
var hid = 'av-' + key + '-' + Math.random().toString(36).slice(2, 7);
|
|
var hoodLite = lighten(c.hoodie, 55);
|
|
return (
|
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 120" class="agent-char-svg" aria-hidden="true">' +
|
|
'<defs>' +
|
|
'<linearGradient id="' + hid + '-bg" x1="0%" y1="0%" x2="100%" y2="100%">' +
|
|
'<stop offset="0%" stop-color="#1a3a5c"/><stop offset="55%" stop-color="#245a82"/><stop offset="100%" stop-color="#1e4a6e"/>' +
|
|
'</linearGradient>' +
|
|
'<linearGradient id="' + hid + '-hood" x1="30%" y1="0%" x2="70%" y2="100%">' +
|
|
'<stop offset="0%" stop-color="' + hoodLite + '"/><stop offset="100%" stop-color="' + c.hoodie + '"/>' +
|
|
'</linearGradient>' +
|
|
'<linearGradient id="' + hid + '-skin" x1="40%" y1="0%" x2="60%" y2="100%">' +
|
|
'<stop offset="0%" stop-color="' + c.skin + '"/><stop offset="100%" stop-color="#d4a07a"/>' +
|
|
'</linearGradient>' +
|
|
'<radialGradient id="' + hid + '-glow" cx="70%" cy="20%" r="50%">' +
|
|
'<stop offset="0%" stop-color="' + c.accent + '" stop-opacity="0.55"/><stop offset="100%" stop-opacity="0"/>' +
|
|
'</radialGradient>' +
|
|
'<filter id="' + hid + '-sh"><feDropShadow dx="0" dy="2" stdDeviation="1.5" flood-opacity="0.3"/></filter>' +
|
|
'</defs>' +
|
|
'<rect width="100" height="120" rx="14" fill="url(#' + hid + '-bg)"/>' +
|
|
'<ellipse cx="78" cy="26" rx="38" ry="32" fill="url(#' + hid + '-glow)"/>' +
|
|
'<ellipse cx="50" cy="100" rx="28" ry="12" fill="rgba(0,0,0,0.22)"/>' +
|
|
'<path d="M18,118 Q18,74 50,68 Q82,74 82,118Z" fill="url(#' + hid + '-hood)" filter="url(#' + hid + '-sh)"/>' +
|
|
'<path d="M20,70 Q50,58 80,70 L76,82 Q50,76 24,82Z" fill="' + hoodLite + '" opacity="0.95"/>' +
|
|
'<path d="M28,68 Q50,48 72,68 L68,78 Q50,72 32,78Z" fill="' + c.hoodie + '"/>' +
|
|
'<ellipse cx="50" cy="54" rx="23" ry="25" fill="url(#' + hid + '-skin)" filter="url(#' + hid + '-sh)"/>' +
|
|
'<ellipse cx="56" cy="56" rx="10" ry="14" fill="rgba(255,255,255,0.12)"/>' +
|
|
(c.hat === 'cap' ? '' : '<path d="' + hairPath(c.style) + '" fill="' + c.hair + '"/>') +
|
|
(c.style === 'glasses'
|
|
? '<ellipse cx="42" cy="52" rx="8" ry="6" fill="none" stroke="#e2e8f0" stroke-width="1.6"/>' +
|
|
'<ellipse cx="58" cy="52" rx="8" ry="6" fill="none" stroke="#e2e8f0" stroke-width="1.6"/>' +
|
|
'<line x1="50" y1="52" x2="50" y2="52" stroke="#e2e8f0" stroke-width="1.5"/>'
|
|
: '') +
|
|
'<ellipse cx="42" cy="52" rx="3.2" ry="3.6" fill="#0f172a"/><ellipse cx="58" cy="52" rx="3.2" ry="3.6" fill="#0f172a"/>' +
|
|
'<ellipse cx="43.2" cy="50.8" rx="1.1" ry="1.3" fill="#fff" opacity="0.85"/><ellipse cx="59.2" cy="50.8" rx="1.1" ry="1.3" fill="#fff" opacity="0.85"/>' +
|
|
'<path d="M44,62 Q50,66 56,62" fill="none" stroke="#b45309" stroke-width="1.5" stroke-linecap="round"/>' +
|
|
'<path d="M16,50 Q50,26 84,50" fill="none" stroke="#e2e8f0" stroke-width="3.5" stroke-linecap="round"/>' +
|
|
'<rect x="10" y="44" width="14" height="18" rx="5" fill="#1e293b" stroke="' + c.accent + '" stroke-width="1.8"/>' +
|
|
'<rect x="12" y="47" width="10" height="12" rx="3" fill="#334155"/>' +
|
|
'<rect x="76" y="44" width="14" height="18" rx="5" fill="#1e293b" stroke="' + c.accent + '" stroke-width="1.8"/>' +
|
|
'<rect x="78" y="47" width="10" height="12" rx="3" fill="#334155"/>' +
|
|
'<path d="M78,60 Q86,72 82,82" fill="none" stroke="#cbd5e1" stroke-width="2.6" stroke-linecap="round"/>' +
|
|
'<circle cx="82" cy="84" r="3.5" fill="' + c.accent + '" stroke="#e2e8f0" stroke-width="1"/>' +
|
|
'<circle cx="88" cy="32" r="3" fill="' + c.accent + '"/>' +
|
|
'<circle cx="14" cy="38" r="2" fill="' + c.accent + '" opacity="0.7"/>' +
|
|
(c.hat === 'cap' ? capSvg(hid, c) : '') +
|
|
'</svg>'
|
|
);
|
|
}
|
|
|
|
function paint(el, key, color, force) {
|
|
if (!el) return;
|
|
var k = (key || '').toLowerCase();
|
|
var c = color || '';
|
|
var sig = k + '|v2|' + c;
|
|
if (!force && el.getAttribute('data-avatar-painted') === sig && el.querySelector('svg')) return;
|
|
el.innerHTML = svgAvatar(k, color);
|
|
el.setAttribute('data-avatar-painted', sig);
|
|
}
|
|
|
|
function paintAll(root, force) {
|
|
root = root || document;
|
|
root.querySelectorAll('[data-agent-avatar]').forEach(function (el) {
|
|
paint(el, el.getAttribute('data-agent-avatar'), el.getAttribute('data-agent-color'), force);
|
|
});
|
|
}
|
|
|
|
return { paint: paint, paintAll: paintAll, svgAvatar: svgAvatar };
|
|
})();
|