Let agents see rendered diagrams and drop Mermaid support

This commit is contained in:
Ian Gulliver
2026-10-21 15:41:51 -07:00
parent ab91285dd4
commit 056c3d202a
18 changed files with 506 additions and 980 deletions
+44 -16
View File
@@ -92,33 +92,62 @@ private func newStage(_ root: StepNode, _ model: String) -> StepNode {
return s
}
func teamNodes(_ id: String, _ agents: [TeamMember]?, stroke: Color?) -> [FlowNode] {
(agents ?? []).enumerated().map { i, a in
FlowNode(id: "\(id)m\(i)", label: "\(a.name.isEmpty ? " " : a.name)\n\(a.model)", style: NodeColors(fill: Palette.bg, stroke: stroke, text: Palette.text))
struct GraphStage {
let name: String
var tint = BoxTint.plain
let agents: [TeamMember]?
let after: [Int]
}
private func quoted(_ s: String) -> String {
"\"" + (s.isEmpty ? " " : s).replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\"") + "\""
}
func stageDiagram(_ stages: [GraphStage]) -> String {
var depth: [Int: Int] = [:]
func level(_ i: Int) -> Int {
if let d = depth[i] {
return d
}
let d = stages[i].after.map { level($0) + 1 }.max() ?? 0
depth[i] = d
return d
}
let levels = stages.indices.map(level)
var lines: [String] = []
for row in 0...(levels.max() ?? 0) {
lines.append("row")
for (i, s) in stages.enumerated() where levels[i] == row {
lines.append(" s\(i) \(quoted(s.name)) \(s.tint.rawValue)")
for (j, a) in (s.agents ?? []).enumerated() {
lines.append(" s\(i)m\(j) \(quoted(a.name)) \(quoted(a.model))")
}
}
}
for (i, s) in stages.enumerated() {
for b in s.after {
lines.append("s\(b) -> s\(i)")
}
}
return lines.joined(separator: "\n")
}
@MainActor
private func stepGraph(_ root: StepNode) -> Flowchart {
var chart = Flowchart(direction: .td)
func walk(_ node: StepNode, _ before: [String]) -> [String] {
private func stepDiagram(_ root: StepNode) -> String {
var stages: [GraphStage] = []
func walk(_ node: StepNode, _ before: [Int]) -> [Int] {
switch node.kind {
case .order:
return node.children.reduce(before) { walk($1, $0) }
case .parallel:
return node.children.flatMap { walk($0, before) }
case .stage:
let id = "n\(chart.order.count)"
chart.node(id, label: node.name.isEmpty ? " " : node.name, shape: .box)
chart.nodes[id]!.members = teamNodes(id, node.agents, stroke: nil)
for b in before {
chart.edges.append(FlowEdge(from: b, to: id, label: nil, style: .solid, arrow: true))
}
return [id]
stages.append(GraphStage(name: node.name, agents: node.agents, after: before))
return [stages.count - 1]
}
}
_ = walk(root, [])
return chart
return stageDiagram(stages)
}
private struct StepLine: Identifiable {
@@ -178,8 +207,7 @@ struct WorkflowEditor: View {
.modifier(FieldStyle())
.padding(.top, 8)
if !root.stageNames().isEmpty {
FlowchartCanvas(layout: layoutFlowchart(stepGraph(root)))
.frame(maxWidth: .infinity, alignment: .leading)
BoxDiagramView(source: stepDiagram(root))
.padding(.top, 12)
}
if !failure.isEmpty {