(host)
| 496 | ]; |
| 497 | |
| 498 | function initTeam(host) { |
| 499 | if (!host) return; |
| 500 | host.innerHTML = ""; |
| 501 | host.classList.add("lc-team"); |
| 502 | |
| 503 | const head = htmlEl("div", { class: "lc-team__head" }); |
| 504 | head.appendChild(htmlEl("span", { class: "lc-muted" }, "orchestrator routes work to specialists, then synthesizes the answer")); |
| 505 | const replayBtn = htmlEl("button", { class: "lc-btn lc-btn--ghost", type: "button" }, "▶ replay one investigation"); |
| 506 | head.appendChild(replayBtn); |
| 507 | host.appendChild(head); |
| 508 | |
| 509 | const svg = svgEl("svg", { viewBox: `0 0 ${TEAM_W} ${TEAM_H}`, width: "100%", role: "img", "aria-label": "Team diagram" }); |
| 510 | host.appendChild(svg); |
| 511 | |
| 512 | // Connectors |
| 513 | const connectors = {}; |
| 514 | [ |
| 515 | { id: "investigator", d: `M 300 90 V ${J_Y} H 105 V 200` }, |
| 516 | { id: "diagnoser", d: "M 300 90 V 200" }, |
| 517 | { id: "remediator", d: `M 300 90 V ${J_Y} H 495 V 200` }, |
| 518 | ].forEach((c) => { |
| 519 | const path = svgEl("path", { |
| 520 | d: c.d, fill: "none", |
| 521 | stroke: "var(--md-default-fg-color--lightest)", |
| 522 | "stroke-width": "1.4", |
| 523 | "stroke-linecap": "round", |
| 524 | }); |
| 525 | svg.appendChild(path); |
| 526 | connectors[c.id] = path; |
| 527 | }); |
| 528 | |
| 529 | // Orchestrator box |
| 530 | const orch = svgEl("g", {}); |
| 531 | orch.appendChild(svgEl("rect", { x: 200, y: 20, width: 200, height: 70, rx: 12, fill: "var(--md-default-bg-color)", stroke: "var(--md-primary-fg-color)", "stroke-width": "1.2", "stroke-opacity": "0.45" })); |
| 532 | addBoxLabels(orch, 200 + 100, 20, 70, "ORCHESTRATOR", "orchestrator", "routes & synthesizes"); |
| 533 | svg.appendChild(orch); |
| 534 | |
| 535 | // Sub-agents |
| 536 | const subBoxes = {}; |
| 537 | TEAM_SUBS.forEach((s) => { |
| 538 | const g = svgEl("g", {}); |
| 539 | const rect = svgEl("rect", { x: s.x, y: SUB_TOP_Y, width: 170, height: 100, rx: 12, fill: "var(--md-default-bg-color)", stroke: "var(--md-default-fg-color--light)", "stroke-width": "1.2", "stroke-opacity": "0.4" }); |
| 540 | g.appendChild(rect); |
| 541 | addBoxLabels(g, s.x + 85, SUB_TOP_Y, 100, "SUB-AGENT", s.label, s.tools); |
| 542 | svg.appendChild(g); |
| 543 | subBoxes[s.id] = rect; |
| 544 | }); |
| 545 | |
| 546 | // Packet |
| 547 | const packet = svgEl("circle", { r: 8, fill: "var(--md-primary-fg-color)", stroke: "var(--md-default-bg-color)", "stroke-width": 2, opacity: 0 }); |
| 548 | svg.appendChild(packet); |
| 549 | |
| 550 | function addBoxLabels(g, cx, top, h, eyebrow, label, sub) { |
| 551 | const e = svgEl("text", { x: cx, y: top + 22, "text-anchor": "middle", "font-family": "var(--md-code-font-family)", "font-size": "10", "letter-spacing": "1.5", fill: "var(--md-primary-fg-color)", opacity: "0.85" }); |
| 552 | e.textContent = eyebrow; |
| 553 | g.appendChild(e); |
| 554 | const l = svgEl("text", { x: cx, y: top + h / 2 + 6, "text-anchor": "middle", "font-family": "var(--md-text-font-family)", "font-size": "14", "font-weight": "600", fill: "var(--md-default-fg-color)" }); |
| 555 | l.textContent = label; |
no test coverage detected