Skip to content

Commit 823036f

Browse files
committed
refactor: add reusable building blocks (WorkflowLoopGraphic, ContextRegions, SpecExecutionRunsDiagram) and update components to use extracted models
1 parent 06d1eb6 commit 823036f

62 files changed

Lines changed: 9915 additions & 4195 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

website/src/components/VisualElements/AgentLoopDiagram.tsx

Lines changed: 209 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import { useStaticAnimationPhase } from '../../hooks/useStaticAnimationPhase';
99
import { useActs } from '../../hooks/useActs';
1010
import { useStrokeDraw } from '../../hooks/useStrokeDraw';
1111
import { useMounted } from '../../hooks/useMounted';
12-
import { CONNECTOR_STYLE, ARROWHEAD_POINTS, arrowOpacity } from './diagramConstants';
12+
import {
13+
CONNECTOR_STYLE,
14+
ARROWHEAD_POINTS,
15+
arrowOpacity,
16+
} from './diagramConstants';
1317

1418
// Layout — ViewBox 520×352
1519
//
@@ -32,12 +36,12 @@ import { CONNECTOR_STYLE, ARROWHEAD_POINTS, arrowOpacity } from './diagramConsta
3236
// Font rule: --font-mono-ai for loop step labels (what the agent does),
3337
// --font-mono-spec for decision/exit labels (what the system decides).
3438
const ACTS = [
35-
{ id: 'perceive', threshold: 0.00 },
36-
{ id: 'reason', threshold: 0.18 },
37-
{ id: 'act', threshold: 0.35 },
38-
{ id: 'observe', threshold: 0.52 },
39-
{ id: 'verify', threshold: 0.70 },
40-
{ id: 'loop', threshold: 0.85 },
39+
{ id: 'perceive', threshold: 0.0 },
40+
{ id: 'reason', threshold: 0.18 },
41+
{ id: 'act', threshold: 0.35 },
42+
{ id: 'observe', threshold: 0.52 },
43+
{ id: 'verify', threshold: 0.7 },
44+
{ id: 'loop', threshold: 0.85 },
4145
] as const;
4246

4347
export default function AgentLoopDiagram() {
@@ -46,25 +50,25 @@ export default function AgentLoopDiagram() {
4650
const mounted = useMounted();
4751

4852
// Node visibility
49-
const reasonReached = mounted && wasReached('reason');
50-
const actReached = mounted && wasReached('act');
53+
const reasonReached = mounted && wasReached('reason');
54+
const actReached = mounted && wasReached('act');
5155
const observeReached = mounted && wasReached('observe');
52-
const verifyReached = mounted && wasReached('verify');
53-
const loopReached = mounted && wasReached('loop');
54-
55-
const arc1Ref = useRef<SVGGeometryElement>(null);
56-
const arc2Ref = useRef<SVGGeometryElement>(null);
57-
const arc3Ref = useRef<SVGGeometryElement>(null);
58-
const arc4Ref = useRef<SVGGeometryElement>(null);
59-
const arc5Ref = useRef<SVGGeometryElement>(null);
56+
const verifyReached = mounted && wasReached('verify');
57+
const loopReached = mounted && wasReached('loop');
58+
59+
const arc1Ref = useRef<SVGGeometryElement>(null);
60+
const arc2Ref = useRef<SVGGeometryElement>(null);
61+
const arc3Ref = useRef<SVGGeometryElement>(null);
62+
const arc4Ref = useRef<SVGGeometryElement>(null);
63+
const arc5Ref = useRef<SVGGeometryElement>(null);
6064
const arcExitRef = useRef<SVGGeometryElement>(null);
6165

62-
const t1 = useStrokeDraw(arc1Ref, phase, 0.18, 0.33);
63-
const t2 = useStrokeDraw(arc2Ref, phase, 0.35, 0.50);
64-
const t3 = useStrokeDraw(arc3Ref, phase, 0.52, 0.67);
65-
const t4 = useStrokeDraw(arc4Ref, phase, 0.70, 0.82);
66+
const t1 = useStrokeDraw(arc1Ref, phase, 0.18, 0.33);
67+
const t2 = useStrokeDraw(arc2Ref, phase, 0.35, 0.5);
68+
const t3 = useStrokeDraw(arc3Ref, phase, 0.52, 0.67);
69+
const t4 = useStrokeDraw(arc4Ref, phase, 0.7, 0.82);
6670
// arc5 (iterate) and arcExit (done) emanate from verify simultaneously — same phase window
67-
const t5 = useStrokeDraw(arc5Ref, phase, 0.85, 0.95);
71+
const t5 = useStrokeDraw(arc5Ref, phase, 0.85, 0.95);
6872
const tExit = useStrokeDraw(arcExitRef, phase, 0.85, 0.95);
6973

7074
return (
@@ -77,130 +81,272 @@ export default function AgentLoopDiagram() {
7781
style={{ display: 'block', maxWidth: '520px', margin: '0 auto' }}
7882
>
7983
{/* ── Perceive node — act 0 (threshold 0.00), visible on mount; no ghost needed ── */}
80-
<DiagramNode x={250} y={55} emoji={EMOJI.microscope} label="perceive" tone="context" reached labelX={270} labelY={33} />
84+
<DiagramNode
85+
x={250}
86+
y={55}
87+
emoji={EMOJI.microscope}
88+
label="perceive"
89+
tone="context"
90+
reached
91+
labelX={270}
92+
labelY={33}
93+
/>
8194

8295
{/* ── Arc 1: perceive → reason ──────────────────────────────────────── */}
8396
<path
8497
ref={arc1Ref}
8598
d="M 294 75 Q 350.71 75.75 372.86 122.48"
8699
{...CONNECTOR_STYLE}
87-
className={clsx(shared.connector, reasonReached && shared.connectorDrawing)}
100+
className={clsx(
101+
shared.connector,
102+
reasonReached && shared.connectorDrawing
103+
)}
88104
/>
89-
<g transform="translate(375,127) rotate(65)" style={{ opacity: arrowOpacity(t1) }}>
105+
<g
106+
transform="translate(375,127) rotate(65)"
107+
style={{ opacity: arrowOpacity(t1) }}
108+
>
90109
<polygon points={ARROWHEAD_POINTS} fill="var(--text-muted)" />
91110
</g>
92111

93112
{/* ── Reason ghost placeholder ──────────────────────────────────────── */}
94-
<Ghost x={351} y={127} width={48} height={48} rx={0}
95-
fill="var(--visual-bg-violet)" stroke="var(--visual-violet)"
96-
mounted={mounted} reached={reasonReached}
113+
<Ghost
114+
x={351}
115+
y={127}
116+
width={48}
117+
height={48}
118+
rx={0}
119+
fill="var(--visual-bg-violet)"
120+
stroke="var(--visual-violet)"
121+
mounted={mounted}
122+
reached={reasonReached}
97123
/>
98124

99125
{/* ── Reason node ───────────────────────────────────────────────────── */}
100-
<DiagramNode x={355} y={131} emoji={EMOJI.brain} label="reason" tone="model" reached={reasonReached} labelX={414.56} labelY={138.03} />
126+
<DiagramNode
127+
x={355}
128+
y={131}
129+
emoji={EMOJI.brain}
130+
label="reason"
131+
tone="model"
132+
reached={reasonReached}
133+
labelX={414.56}
134+
labelY={138.03}
135+
/>
101136

102137
{/* ── Arc 2: reason → act ───────────────────────────────────────────── */}
103138
<path
104139
ref={arc2Ref}
105140
d="M 375 175 Q 381.47 226.62 339.47 247.75"
106141
{...CONNECTOR_STYLE}
107-
className={clsx(shared.connector, actReached && shared.connectorDrawing)}
142+
className={clsx(
143+
shared.connector,
144+
actReached && shared.connectorDrawing
145+
)}
108146
/>
109-
<g transform="translate(335,250) rotate(153)" style={{ opacity: arrowOpacity(t2) }}>
147+
<g
148+
transform="translate(335,250) rotate(153)"
149+
style={{ opacity: arrowOpacity(t2) }}
150+
>
110151
<polygon points={ARROWHEAD_POINTS} fill="var(--text-muted)" />
111152
</g>
112153

113154
{/* ── Act ghost placeholder ─────────────────────────────────────────── */}
114-
<Ghost x={311} y={250} width={48} height={48} rx={0}
115-
fill="var(--visual-bg-cyan)" stroke="var(--visual-cyan)"
116-
mounted={mounted} reached={actReached}
155+
<Ghost
156+
x={311}
157+
y={250}
158+
width={48}
159+
height={48}
160+
rx={0}
161+
fill="var(--visual-bg-cyan)"
162+
stroke="var(--visual-cyan)"
163+
mounted={mounted}
164+
reached={actReached}
117165
/>
118166

119167
{/* ── Act node ──────────────────────────────────────────────────────── */}
120-
<DiagramNode x={315} y={254} emoji={EMOJI.act} label="act" tone="system" reached={actReached} labelX={359.34} labelY={307.97} />
168+
<DiagramNode
169+
x={315}
170+
y={254}
171+
emoji={EMOJI.act}
172+
label="act"
173+
tone="system"
174+
reached={actReached}
175+
labelX={359.34}
176+
labelY={307.97}
177+
/>
121178

122179
{/* ── Arc 3: act → observe ─────────────────────────────────────────── */}
123180
<path
124181
ref={arc3Ref}
125182
d="M 311 274 Q 270 304 233.04 276.95"
126183
{...CONNECTOR_STYLE}
127-
className={clsx(shared.connector, observeReached && shared.connectorDrawing)}
184+
className={clsx(
185+
shared.connector,
186+
observeReached && shared.connectorDrawing
187+
)}
128188
/>
129-
<g transform="translate(229,274) rotate(-144)" style={{ opacity: arrowOpacity(t3) }}>
189+
<g
190+
transform="translate(229,274) rotate(-144)"
191+
style={{ opacity: arrowOpacity(t3) }}
192+
>
130193
<polygon points={ARROWHEAD_POINTS} fill="var(--text-muted)" />
131194
</g>
132195

133196
{/* ── Observe ghost placeholder ─────────────────────────────────────── */}
134-
<Ghost x={181} y={250} width={48} height={48} rx={0}
135-
fill="var(--visual-bg-magenta)" stroke="var(--visual-magenta)"
136-
mounted={mounted} reached={observeReached}
197+
<Ghost
198+
x={181}
199+
y={250}
200+
width={48}
201+
height={48}
202+
rx={0}
203+
fill="var(--visual-bg-magenta)"
204+
stroke="var(--visual-magenta)"
205+
mounted={mounted}
206+
reached={observeReached}
137207
/>
138208

139209
{/* ── Observe node ─────────────────────────────────────────────────── */}
140-
<DiagramNode x={185} y={254} emoji={EMOJI.observe} label="observe" tone="magenta" reached={observeReached} labelX={180.66} labelY={307.97} />
210+
<DiagramNode
211+
x={185}
212+
y={254}
213+
emoji={EMOJI.observe}
214+
label="observe"
215+
tone="magenta"
216+
reached={observeReached}
217+
labelX={180.66}
218+
labelY={307.97}
219+
/>
141220

142221
{/* ── Arc 4: observe → verify ───────────────────────────────────────── */}
143222
<path
144223
ref={arc4Ref}
145224
d="M 205 250 Q 158.53 226.62 164.38 179.96"
146225
{...CONNECTOR_STYLE}
147-
className={clsx(shared.connector, verifyReached && shared.connectorDrawing)}
226+
className={clsx(
227+
shared.connector,
228+
verifyReached && shared.connectorDrawing
229+
)}
148230
/>
149-
<g transform="translate(165,175) rotate(-83)" style={{ opacity: arrowOpacity(t4) }}>
231+
<g
232+
transform="translate(165,175) rotate(-83)"
233+
style={{ opacity: arrowOpacity(t4) }}
234+
>
150235
<polygon points={ARROWHEAD_POINTS} fill="var(--text-muted)" />
151236
</g>
152237

153238
{/* ── Verify ghost placeholder ──────────────────────────────────────── */}
154-
<Ghost x={141} y={127} width={48} height={48} rx={0}
155-
fill="var(--visual-bg-warning)" stroke="var(--visual-warning)"
156-
mounted={mounted} reached={verifyReached}
239+
<Ghost
240+
x={141}
241+
y={127}
242+
width={48}
243+
height={48}
244+
rx={0}
245+
fill="var(--visual-bg-warning)"
246+
stroke="var(--visual-warning)"
247+
mounted={mounted}
248+
reached={verifyReached}
157249
/>
158250

159251
{/* ── Verify node ───────────────────────────────────────────────────── */}
160-
<DiagramNode x={145} y={131} emoji={EMOJI.ruler} label="verify" tone="warning" reached={verifyReached} labelX={108} labelY={155} />
252+
<DiagramNode
253+
x={145}
254+
y={131}
255+
emoji={EMOJI.ruler}
256+
label="verify"
257+
tone="warning"
258+
reached={verifyReached}
259+
labelX={108}
260+
labelY={155}
261+
/>
161262

162263
{/* ── Arc 5: verify → perceive (iterate / "No") ────────────────────── */}
163264
<path
164265
ref={arc5Ref}
165266
d="M 165 127 Q 189.29 75.75 241 75.07"
166267
{...CONNECTOR_STYLE}
167-
className={clsx(shared.connector, loopReached && shared.connectorDrawing)}
268+
className={clsx(
269+
shared.connector,
270+
loopReached && shared.connectorDrawing
271+
)}
168272
/>
169-
<g transform="translate(246,75) rotate(-1)" style={{ opacity: arrowOpacity(t5) }}>
273+
<g
274+
transform="translate(246,75) rotate(-1)"
275+
style={{ opacity: arrowOpacity(t5) }}
276+
>
170277
<polygon points={ARROWHEAD_POINTS} fill="var(--text-muted)" />
171278
</g>
172-
<text x={197} y={78}
279+
<text
280+
x={197}
281+
y={78}
173282
fill="var(--text-muted)"
174283
style={{ fontFamily: 'var(--font-mono-spec)' }}
175-
fontSize={9} textAnchor="middle"
176-
className={clsx(styles.decisionLabel, loopReached && styles.decisionLabelIn)}
177-
>No</text>
284+
fontSize={9}
285+
textAnchor="middle"
286+
className={clsx(
287+
styles.decisionLabel,
288+
loopReached && styles.decisionLabelIn
289+
)}
290+
>
291+
No
292+
</text>
178293

179294
{/* ── Exit arc: verify → done ("Yes") ──────────────────────────────── */}
180295
<path
181296
ref={arcExitRef}
182297
d="M 141 151 Q 91.73 181.96 95.63 235.01"
183298
{...CONNECTOR_STYLE}
184-
className={clsx(shared.connector, loopReached && shared.connectorDrawing)}
299+
className={clsx(
300+
shared.connector,
301+
loopReached && shared.connectorDrawing
302+
)}
185303
/>
186-
<g transform="translate(96,240) rotate(86)" style={{ opacity: arrowOpacity(tExit) }}>
304+
<g
305+
transform="translate(96,240) rotate(86)"
306+
style={{ opacity: arrowOpacity(tExit) }}
307+
>
187308
<polygon points={ARROWHEAD_POINTS} fill="var(--text-muted)" />
188309
</g>
189-
<text x={127} y={196}
310+
<text
311+
x={127}
312+
y={196}
190313
fill="var(--text-muted)"
191314
style={{ fontFamily: 'var(--font-mono-spec)' }}
192-
fontSize={9} textAnchor="middle"
193-
className={clsx(styles.decisionLabel, loopReached && styles.decisionLabelIn)}
194-
>Yes</text>
315+
fontSize={9}
316+
textAnchor="middle"
317+
className={clsx(
318+
styles.decisionLabel,
319+
loopReached && styles.decisionLabelIn
320+
)}
321+
>
322+
Yes
323+
</text>
195324

196325
{/* ── Done ghost placeholder ────────────────────────────────────────── */}
197-
<Ghost x={72} y={240} width={48} height={48} rx={0}
198-
fill="var(--visual-bg-success)" stroke="var(--visual-success)"
199-
mounted={mounted} reached={loopReached}
326+
<Ghost
327+
x={72}
328+
y={240}
329+
width={48}
330+
height={48}
331+
rx={0}
332+
fill="var(--visual-bg-success)"
333+
stroke="var(--visual-success)"
334+
mounted={mounted}
335+
reached={loopReached}
200336
/>
201337

202338
{/* ── Done node ─────────────────────────────────────────────────────── */}
203-
<DiagramNode x={76} y={244} emoji={EMOJI.check} label="done" tone="success" reached={loopReached} labelX={96} labelY={300} labelVoice="spec" />
339+
<DiagramNode
340+
x={76}
341+
y={244}
342+
emoji={EMOJI.check}
343+
label="done"
344+
tone="success"
345+
reached={loopReached}
346+
labelX={96}
347+
labelY={300}
348+
labelVoice="spec"
349+
/>
204350
</svg>
205351
);
206352
}

0 commit comments

Comments
 (0)