Spaces:
Sleeping
Sleeping
File size: 3,181 Bytes
6085b61 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | """Visualise the LangGraph flow with the current node highlighted."""
from __future__ import annotations
from typing import Optional
def render_graph(
current_node: Optional[str] = None, state: Optional[dict] = None
) -> str:
"""Return an HTML+CSS flow diagram as a string.
Supports both single-agent (planner → executor ↔ verify → git)
and multi-agent (manager → planner → coder ↔ executor → verify → reviewer → git) flows.
Determines mode from the state's `current_agent` field, or by checking if
the current_node is specific to multi-agent mode.
"""
if state and state.get("current_agent") in ("manager", "coder", "reviewer"):
is_multi = True
elif current_node in ("manager", "coder", "reviewer"):
is_multi = True
else:
is_multi = False
if is_multi:
nodes = [
("manager", "Manager"),
("planner", "Planner"),
("coder", "Coder"),
("executor", "Executor"),
("verify", "Verify"),
("reviewer", "Reviewer"),
("git_workflow", "Git Workflow"),
("end", "END"),
]
else:
nodes = [
("planner", "Planner"),
("executor", "Executor"),
("verify", "Verify"),
("git_workflow", "Git Workflow"),
("end", "END"),
]
def _color(nid: str) -> str:
if nid == current_node:
return "#22c55e"
if nid == "end":
return "#f3f4f6"
return "#e5e7eb"
def _text_color(nid: str) -> str:
return "#ffffff" if nid == current_node else "#6b7280"
def _glow(nid: str) -> str:
return (
"box-shadow: 0 0 12px rgba(34,197,94,0.6);" if nid == current_node else ""
)
node_divs = []
for nid, label in nodes:
bg = _color(nid)
tc = _text_color(nid)
glow = _glow(nid)
node_divs.append(
f'<div style="display:flex;flex-direction:column;align-items:center;'
f'gap:4px">'
f'<div style="background:{bg};color:{tc};padding:8px 18px;'
f"border-radius:8px;font-weight:600;font-size:14px;"
f'transition:all 0.3s ease;{glow}">{label}</div>'
f"</div>"
)
# Build arrows between consecutive nodes
arrow_divs = []
for i in range(len(node_divs) - 1):
arrow_divs.append(node_divs[i])
# Add loop indicator between coder↔executor
if is_multi and nodes[i][0] == "executor":
arrow_divs.append(
'<div style="color:#9ca3af;font-size:12px;writing-mode:vertical-lr;'
'text-orientation:mixed;opacity:0.5">↻ loop</div>'
)
arrow_divs.append(node_divs[i])
arrow_divs.append('<div style="color:#9ca3af;font-size:20px">→</div>')
arrow_divs.append(node_divs[-1])
html = f"""
<div style="font-family:'Segoe UI',system-ui,sans-serif;padding:8px 0">
<div style="display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap">
{''.join(arrow_divs)}
</div>
</div>
"""
return html
|