@osolmaz/pi-workflows 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +182 -0
- package/dist/extension/executor.d.ts +58 -0
- package/dist/extension/executor.js +201 -0
- package/dist/extension/executor.js.map +1 -0
- package/dist/extension/index.d.ts +17 -0
- package/dist/extension/index.js +504 -0
- package/dist/extension/index.js.map +1 -0
- package/dist/extension/widget.d.ts +21 -0
- package/dist/extension/widget.js +142 -0
- package/dist/extension/widget.js.map +1 -0
- package/dist/render/ansi.d.ts +16 -0
- package/dist/render/ansi.js +42 -0
- package/dist/render/ansi.js.map +1 -0
- package/dist/render/canvas.d.ts +40 -0
- package/dist/render/canvas.js +177 -0
- package/dist/render/canvas.js.map +1 -0
- package/dist/render/format.d.ts +3 -0
- package/dist/render/format.js +17 -0
- package/dist/render/format.js.map +1 -0
- package/dist/render/graph-render.d.ts +22 -0
- package/dist/render/graph-render.js +520 -0
- package/dist/render/graph-render.js.map +1 -0
- package/dist/render/graph.d.ts +46 -0
- package/dist/render/graph.js +272 -0
- package/dist/render/graph.js.map +1 -0
- package/dist/viewer/cli.d.ts +10 -0
- package/dist/viewer/cli.js +132 -0
- package/dist/viewer/cli.js.map +1 -0
- package/dist/viewer/render.d.ts +19 -0
- package/dist/viewer/render.js +162 -0
- package/dist/viewer/render.js.map +1 -0
- package/dist/viewer/tui.d.ts +11 -0
- package/dist/viewer/tui.js +140 -0
- package/dist/viewer/tui.js.map +1 -0
- package/dist/viewer/watch.d.ts +9 -0
- package/dist/viewer/watch.js +46 -0
- package/dist/viewer/watch.js.map +1 -0
- package/dist/workflows/decision.d.ts +25 -0
- package/dist/workflows/decision.js +96 -0
- package/dist/workflows/decision.js.map +1 -0
- package/dist/workflows/definition.d.ts +9 -0
- package/dist/workflows/definition.js +61 -0
- package/dist/workflows/definition.js.map +1 -0
- package/dist/workflows/engine.d.ts +65 -0
- package/dist/workflows/engine.js +574 -0
- package/dist/workflows/engine.js.map +1 -0
- package/dist/workflows/errors.d.ts +9 -0
- package/dist/workflows/errors.js +24 -0
- package/dist/workflows/errors.js.map +1 -0
- package/dist/workflows/graph.d.ts +17 -0
- package/dist/workflows/graph.js +127 -0
- package/dist/workflows/graph.js.map +1 -0
- package/dist/workflows/index.d.ts +11 -0
- package/dist/workflows/index.js +11 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/json.d.ts +14 -0
- package/dist/workflows/json.js +134 -0
- package/dist/workflows/json.js.map +1 -0
- package/dist/workflows/loader.d.ts +28 -0
- package/dist/workflows/loader.js +94 -0
- package/dist/workflows/loader.js.map +1 -0
- package/dist/workflows/schema.d.ts +7 -0
- package/dist/workflows/schema.js +176 -0
- package/dist/workflows/schema.js.map +1 -0
- package/dist/workflows/shell.d.ts +9 -0
- package/dist/workflows/shell.js +177 -0
- package/dist/workflows/shell.js.map +1 -0
- package/dist/workflows/store.d.ts +35 -0
- package/dist/workflows/store.js +181 -0
- package/dist/workflows/store.js.map +1 -0
- package/dist/workflows/text.d.ts +10 -0
- package/dist/workflows/text.js +32 -0
- package/dist/workflows/text.js.map +1 -0
- package/dist/workflows/types.d.ts +280 -0
- package/dist/workflows/types.js +2 -0
- package/dist/workflows/types.js.map +1 -0
- package/docs/development.md +130 -0
- package/docs/run-bundles.md +114 -0
- package/docs/workflows.md +311 -0
- package/examples/workflows/autoimplement.workflow.ts +92 -0
- package/examples/workflows/autoresearch.workflow.ts +139 -0
- package/examples/workflows/branch.workflow.ts +63 -0
- package/examples/workflows/echo.workflow.ts +23 -0
- package/examples/workflows/elegant-solution.workflow.ts +95 -0
- package/examples/workflows/shell.workflow.ts +31 -0
- package/examples/workflows/two-turn.workflow.ts +64 -0
- package/package.json +80 -0
- package/src/extension/executor.ts +251 -0
- package/src/extension/index.ts +627 -0
- package/src/extension/widget.ts +183 -0
- package/src/render/ansi.ts +47 -0
- package/src/render/canvas.ts +196 -0
- package/src/render/format.ts +19 -0
- package/src/render/graph-render.ts +738 -0
- package/src/render/graph.ts +341 -0
- package/src/viewer/cli.ts +150 -0
- package/src/viewer/render.ts +236 -0
- package/src/viewer/tui.ts +159 -0
- package/src/viewer/watch.ts +55 -0
- package/src/workflows/decision.ts +127 -0
- package/src/workflows/definition.ts +104 -0
- package/src/workflows/engine.ts +793 -0
- package/src/workflows/errors.ts +27 -0
- package/src/workflows/graph.ts +161 -0
- package/src/workflows/index.ts +76 -0
- package/src/workflows/json.ts +155 -0
- package/src/workflows/loader.ts +123 -0
- package/src/workflows/schema.ts +218 -0
- package/src/workflows/shell.ts +199 -0
- package/src/workflows/store.ts +234 -0
- package/src/workflows/text.ts +34 -0
- package/src/workflows/types.ts +318 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import { ansi, sanitizeText } from "./ansi.js";
|
|
2
|
+
import { CharCanvas } from "./canvas.js";
|
|
3
|
+
import { formatDuration } from "./format.js";
|
|
4
|
+
import { layoutGraph, } from "./graph.js";
|
|
5
|
+
const STATUS_GLYPHS = {
|
|
6
|
+
completed: "✓",
|
|
7
|
+
failed: "✗",
|
|
8
|
+
active: "◐",
|
|
9
|
+
waiting: "⏸",
|
|
10
|
+
cancelled: "~",
|
|
11
|
+
queued: "·",
|
|
12
|
+
};
|
|
13
|
+
const STATUS_STYLES = {
|
|
14
|
+
completed: "ok",
|
|
15
|
+
failed: "fail",
|
|
16
|
+
active: "active",
|
|
17
|
+
waiting: "warn",
|
|
18
|
+
cancelled: "warn",
|
|
19
|
+
queued: "dim",
|
|
20
|
+
};
|
|
21
|
+
const CELL_GAP = 4;
|
|
22
|
+
const GUTTER_GAP = 2;
|
|
23
|
+
/** Rows a node cell occupies: boxes add a border row above and below. */
|
|
24
|
+
function cellHeight(nodeStyle) {
|
|
25
|
+
return nodeStyle === "box" ? 3 : 1;
|
|
26
|
+
}
|
|
27
|
+
function paint(text, style) {
|
|
28
|
+
switch (style) {
|
|
29
|
+
case "taken":
|
|
30
|
+
case "ok":
|
|
31
|
+
return ansi.green(text);
|
|
32
|
+
case "active":
|
|
33
|
+
return ansi.cyan(text);
|
|
34
|
+
case "back":
|
|
35
|
+
case "warn":
|
|
36
|
+
return ansi.yellow(text);
|
|
37
|
+
case "fail":
|
|
38
|
+
return ansi.red(text);
|
|
39
|
+
case "dim":
|
|
40
|
+
return ansi.dim(text);
|
|
41
|
+
default:
|
|
42
|
+
return text;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function latestVisibleAttempt(steps, nodeId) {
|
|
46
|
+
for (let index = steps.length - 1; index >= 0; index -= 1) {
|
|
47
|
+
if (steps[index]?.nodeId === nodeId) {
|
|
48
|
+
return steps[index];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
function deriveNodeStatus(view, nodeId, visibleSteps, atLatestStep) {
|
|
54
|
+
const state = view.state;
|
|
55
|
+
if (atLatestStep && state.currentNode === nodeId) {
|
|
56
|
+
return "active";
|
|
57
|
+
}
|
|
58
|
+
if (atLatestStep && state.waitingOn === nodeId) {
|
|
59
|
+
return "waiting";
|
|
60
|
+
}
|
|
61
|
+
const attempt = latestVisibleAttempt(visibleSteps, nodeId);
|
|
62
|
+
if (!attempt) {
|
|
63
|
+
return "queued";
|
|
64
|
+
}
|
|
65
|
+
// While scrubbing, the selected step's node reads as the active position.
|
|
66
|
+
if (!atLatestStep && visibleSteps.at(-1)?.nodeId === nodeId) {
|
|
67
|
+
return "active";
|
|
68
|
+
}
|
|
69
|
+
switch (attempt.outcome) {
|
|
70
|
+
case "ok":
|
|
71
|
+
return "completed";
|
|
72
|
+
case "cancelled":
|
|
73
|
+
return "cancelled";
|
|
74
|
+
default:
|
|
75
|
+
return "failed";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function renderCellText(view, cell, visibleSteps, atLatestStep, now, nodeStyle) {
|
|
79
|
+
if (cell.kind === "virtual") {
|
|
80
|
+
return { cell, text: "", status: null, width: 1 };
|
|
81
|
+
}
|
|
82
|
+
const state = view.state;
|
|
83
|
+
const nodeId = cell.nodeId;
|
|
84
|
+
const status = deriveNodeStatus(view, nodeId, visibleSteps, atLatestStep);
|
|
85
|
+
const nodeType = view.snapshot?.nodes[nodeId]?.nodeType ?? "?";
|
|
86
|
+
const attempt = latestVisibleAttempt(visibleSteps, nodeId);
|
|
87
|
+
const attempts = visibleSteps.filter((step) => step.nodeId === nodeId).length;
|
|
88
|
+
const parts = [`${nodeId} [${nodeType}]`];
|
|
89
|
+
if (atLatestStep && state.currentNode === nodeId) {
|
|
90
|
+
const startedAt = state.currentNodeStartedAt
|
|
91
|
+
? Date.parse(state.currentNodeStartedAt)
|
|
92
|
+
: now.getTime();
|
|
93
|
+
parts.push(`running ${formatDuration(now.getTime() - startedAt)}`);
|
|
94
|
+
if (state.statusDetail) {
|
|
95
|
+
// statusDetail can be set by workflow authors; keep terminal-safe.
|
|
96
|
+
parts.push(`· ${sanitizeText(state.statusDetail)}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (attempt) {
|
|
100
|
+
const durationMs = Date.parse(attempt.finishedAt) - Date.parse(attempt.startedAt);
|
|
101
|
+
parts.push(formatDuration(durationMs));
|
|
102
|
+
}
|
|
103
|
+
if (attempts > 1) {
|
|
104
|
+
parts.push(`×${attempts}`);
|
|
105
|
+
}
|
|
106
|
+
const text = parts.join(" ");
|
|
107
|
+
// Width includes the status glyph and the space after it; boxes add a
|
|
108
|
+
// border and one padding column on each side.
|
|
109
|
+
const contentWidth = text.length + 2;
|
|
110
|
+
return { cell, text, status, width: nodeStyle === "box" ? contentWidth + 4 : contentWidth };
|
|
111
|
+
}
|
|
112
|
+
/** Transitions actually taken between the visible steps, as "from->to". */
|
|
113
|
+
function takenTransitions(visibleSteps) {
|
|
114
|
+
const transitions = new Set();
|
|
115
|
+
for (let index = 1; index < visibleSteps.length; index += 1) {
|
|
116
|
+
transitions.add(`${visibleSteps[index - 1]?.nodeId}->${visibleSteps[index]?.nodeId}`);
|
|
117
|
+
}
|
|
118
|
+
return transitions;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Render the graph pane. `selectedStepIndex` scrubs the replay position;
|
|
122
|
+
* pass `steps.length - 1` (or larger) for the live view.
|
|
123
|
+
*/
|
|
124
|
+
export function renderGraphLines(view, selectedStepIndex, now = new Date(), options = {}) {
|
|
125
|
+
const snapshot = view.snapshot;
|
|
126
|
+
if (!snapshot) {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
const nodeStyle = options.nodeStyle ?? "line";
|
|
130
|
+
const layout = layoutGraph(snapshot);
|
|
131
|
+
const steps = view.state.steps;
|
|
132
|
+
const boundedIndex = Math.min(Math.max(selectedStepIndex, -1), steps.length - 1);
|
|
133
|
+
const atLatestStep = boundedIndex >= steps.length - 1;
|
|
134
|
+
const visibleSteps = steps.slice(0, boundedIndex + 1);
|
|
135
|
+
const transitions = takenTransitions(visibleSteps);
|
|
136
|
+
const activePair = derivePairInFlight(view, visibleSteps, atLatestStep);
|
|
137
|
+
const rendered = layout.ranks.map((rank) => rank.map((cell) => renderCellText(view, cell, visibleSteps, atLatestStep, now, nodeStyle)));
|
|
138
|
+
// Column positions: pack cells left to right per rank, then center every
|
|
139
|
+
// rank against the widest one so vertical edges stay near-vertical.
|
|
140
|
+
const rankWidths = rendered.map((cells) => cells.reduce((sum, cell) => sum + cell.width, 0) + Math.max(0, cells.length - 1) * CELL_GAP);
|
|
141
|
+
const graphWidth = Math.max(0, ...rankWidths);
|
|
142
|
+
const geometry = rendered.map((cells, rankIndex) => {
|
|
143
|
+
const centers = [];
|
|
144
|
+
let x = Math.floor((graphWidth - (rankWidths[rankIndex] ?? 0)) / 2);
|
|
145
|
+
for (const cell of cells) {
|
|
146
|
+
// Single-cell ranks share the exact graph center so chains render as
|
|
147
|
+
// straight vertical lines instead of one-column elbows.
|
|
148
|
+
centers.push(cells.length === 1 ? Math.floor(graphWidth / 2) : x + Math.floor(cell.width / 2));
|
|
149
|
+
x += cell.width + CELL_GAP;
|
|
150
|
+
}
|
|
151
|
+
return { cells, centers };
|
|
152
|
+
});
|
|
153
|
+
// Horizontal edge geometry (exit/entry columns, pixel-space track rows) is
|
|
154
|
+
// fully decided before vertical placement, so row budgeting is exact.
|
|
155
|
+
const strips = geometry.map((_rank, rankIndex) => computeStripGeometry(layout, rankIndex, geometry));
|
|
156
|
+
const lanes = backEdgeLanes(layout);
|
|
157
|
+
const placed = [];
|
|
158
|
+
// Entry lanes above the first rank need an arrow row of their own.
|
|
159
|
+
const topLanes = lanes.above(0).length;
|
|
160
|
+
let y = topLanes > 0 ? topLanes + 1 : 0;
|
|
161
|
+
for (const [rankIndex, rank] of geometry.entries()) {
|
|
162
|
+
placed.push({ ...rank, y });
|
|
163
|
+
y +=
|
|
164
|
+
cellHeight(nodeStyle) +
|
|
165
|
+
lanes.below(rankIndex).length +
|
|
166
|
+
gapRows(strips[rankIndex], rankIndex, layout.ranks.length) +
|
|
167
|
+
lanes.above(rankIndex + 1).length;
|
|
168
|
+
}
|
|
169
|
+
const canvas = new CharCanvas();
|
|
170
|
+
drawNodes(canvas, placed, layout, transitions, nodeStyle);
|
|
171
|
+
const labels = drawSegments(canvas, placed, strips, layout, transitions, activePair, graphWidth, nodeStyle, lanes);
|
|
172
|
+
drawBackEdges(canvas, placed, layout, transitions, graphWidth, nodeStyle, lanes);
|
|
173
|
+
// Labels go on last, once every line is on the canvas: placement can then
|
|
174
|
+
// guarantee no later stroke crosses through a label.
|
|
175
|
+
for (const label of labels) {
|
|
176
|
+
drawSegmentLabel(canvas, label);
|
|
177
|
+
}
|
|
178
|
+
return canvas.render(paint);
|
|
179
|
+
}
|
|
180
|
+
function backEdgeLanes(layout) {
|
|
181
|
+
const edges = layout.edges.filter((edge) => edge.isBackEdge);
|
|
182
|
+
return {
|
|
183
|
+
edges,
|
|
184
|
+
below: (rank) => edges.filter((edge) => layout.rankOfNode.get(edge.from) === rank),
|
|
185
|
+
above: (rank) => edges.filter((edge) => layout.rankOfNode.get(edge.to) === rank),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/** The transition currently in flight, drawn in the active style. */
|
|
189
|
+
function derivePairInFlight(view, visibleSteps, atLatestStep) {
|
|
190
|
+
const state = view.state;
|
|
191
|
+
if (atLatestStep) {
|
|
192
|
+
if (state.status === "running" && state.currentNode && visibleSteps.length > 0) {
|
|
193
|
+
return `${visibleSteps.at(-1)?.nodeId}->${state.currentNode}`;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
if (visibleSteps.length >= 2) {
|
|
198
|
+
return `${visibleSteps.at(-2)?.nodeId}->${visibleSteps.at(-1)?.nodeId}`;
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
/** Rows between rank r's cell rows and rank r+1's cell rows. */
|
|
203
|
+
function gapRows(strip, rank, rankCount) {
|
|
204
|
+
if (strip.segments.length === 0) {
|
|
205
|
+
return rank < rankCount - 1 ? 1 : 0;
|
|
206
|
+
}
|
|
207
|
+
// Straight unlabeled strips need no track rows: one line row, one arrow row.
|
|
208
|
+
if (strip.straight) {
|
|
209
|
+
return 2;
|
|
210
|
+
}
|
|
211
|
+
// Labelled strips reserve one extra row below the tracks so labels that do
|
|
212
|
+
// not fit on their horizontal run always have a collision-free home.
|
|
213
|
+
return 2 + strip.trackCount + (strip.hasLabels ? 1 : 0);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Resolve a strip (all segments between rank r and rank r+1) to final pixel
|
|
217
|
+
* geometry: exit and entry columns, and a horizontal track row per segment.
|
|
218
|
+
*
|
|
219
|
+
* Two rules make the drawing collision-free by construction. First, when
|
|
220
|
+
* several edges leave or enter one cell, they fan out over separate columns
|
|
221
|
+
* (ordered by the far end so lines inside a fan never cross), so corner
|
|
222
|
+
* characters cannot merge into fake junctions. Second, tracks are assigned
|
|
223
|
+
* from the final pixel spans, so two horizontal runs share a row only when
|
|
224
|
+
* they cannot touch, corners included.
|
|
225
|
+
*/
|
|
226
|
+
function computeStripGeometry(layout, rank, geometry) {
|
|
227
|
+
const strip = layout.segments.filter((segment) => segment.rank === rank);
|
|
228
|
+
const top = geometry[rank];
|
|
229
|
+
const bottom = geometry[rank + 1];
|
|
230
|
+
if (strip.length === 0 || !top || !bottom) {
|
|
231
|
+
return { segments: [], trackCount: 1, hasLabels: false, straight: true };
|
|
232
|
+
}
|
|
233
|
+
const exitOffsets = fanOffsets(strip, "from", top, bottom);
|
|
234
|
+
const entryOffsets = fanOffsets(strip, "to", top, bottom);
|
|
235
|
+
const resolved = strip.map((segment) => {
|
|
236
|
+
const fromX = top.centers[segment.fromCell] + (exitOffsets.get(segment.edgeId) ?? 0);
|
|
237
|
+
let toX = bottom.centers[segment.toCell] + (entryOffsets.get(segment.edgeId) ?? 0);
|
|
238
|
+
const targetIsNode = bottom.cells[segment.toCell].cell.kind === "node";
|
|
239
|
+
// A one-column jog reads as noise; draw it straight into the target,
|
|
240
|
+
// whose rendered cell is wide enough to absorb the offset. Virtual
|
|
241
|
+
// cells are exactly one column wide, so they must never be snapped.
|
|
242
|
+
if (targetIsNode && Math.abs(toX - fromX) <= 1) {
|
|
243
|
+
toX = fromX;
|
|
244
|
+
}
|
|
245
|
+
return { edgeId: segment.edgeId, label: segment.label, fromX, toX, targetIsNode };
|
|
246
|
+
});
|
|
247
|
+
// First-fit track assignment over pixel spans; straight unlabeled
|
|
248
|
+
// segments draw a plain vertical line and need no track row.
|
|
249
|
+
const segments = [];
|
|
250
|
+
const trackRanges = [];
|
|
251
|
+
for (const segment of resolved.toSorted((a, b) => a.fromX - b.fromX)) {
|
|
252
|
+
let track = 0;
|
|
253
|
+
if (segment.fromX !== segment.toX || segment.label !== undefined) {
|
|
254
|
+
const span = [
|
|
255
|
+
Math.min(segment.fromX, segment.toX),
|
|
256
|
+
Math.max(segment.fromX, segment.toX),
|
|
257
|
+
];
|
|
258
|
+
track = trackRanges.findIndex((ranges) => ranges.every(([start, end]) => span[1] < start || span[0] > end));
|
|
259
|
+
if (track === -1) {
|
|
260
|
+
track = trackRanges.length;
|
|
261
|
+
trackRanges.push([]);
|
|
262
|
+
}
|
|
263
|
+
trackRanges[track].push(span);
|
|
264
|
+
}
|
|
265
|
+
segments.push({ ...segment, track });
|
|
266
|
+
}
|
|
267
|
+
return {
|
|
268
|
+
segments,
|
|
269
|
+
trackCount: Math.max(1, trackRanges.length),
|
|
270
|
+
hasLabels: segments.some((segment) => segment.label !== undefined),
|
|
271
|
+
straight: segments.every((segment) => segment.fromX === segment.toX && segment.label === undefined),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Fan columns for edges sharing a cell: segment i (ordered by the far
|
|
276
|
+
* end's x) gets column center - 2*(n-1-i), clamped to the cell, never
|
|
277
|
+
* right of center. Forward fans stay at or left of center while back-edge
|
|
278
|
+
* anchors sit right of center, so the two can never collide.
|
|
279
|
+
*/
|
|
280
|
+
function fanOffsets(strip, side, top, bottom) {
|
|
281
|
+
const [ownRank, ownCell, farRank, farCell] = side === "from"
|
|
282
|
+
? [top, (s) => s.fromCell, bottom, (s) => s.toCell]
|
|
283
|
+
: [bottom, (s) => s.toCell, top, (s) => s.fromCell];
|
|
284
|
+
const offsets = new Map();
|
|
285
|
+
const groups = new Map();
|
|
286
|
+
for (const segment of strip) {
|
|
287
|
+
// Virtual cells are one column wide and always have one edge per side.
|
|
288
|
+
if (ownRank.cells[ownCell(segment)].cell.kind === "node") {
|
|
289
|
+
groups.set(ownCell(segment), [...(groups.get(ownCell(segment)) ?? []), segment]);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (const [cellIndex, group] of groups) {
|
|
293
|
+
if (group.length < 2) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const cell = ownRank.cells[cellIndex];
|
|
297
|
+
const maxOffset = Math.max(1, Math.floor(cell.width / 2) - 1);
|
|
298
|
+
const ordered = group.toSorted((a, b) => farRank.centers[farCell(a)] - farRank.centers[farCell(b)]);
|
|
299
|
+
for (const [index, segment] of ordered.entries()) {
|
|
300
|
+
const offset = -2 * (ordered.length - 1 - index);
|
|
301
|
+
offsets.set(segment.edgeId, Math.max(-maxOffset, offset));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return offsets;
|
|
305
|
+
}
|
|
306
|
+
const BOX_CHARS = {
|
|
307
|
+
light: { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│" },
|
|
308
|
+
heavy: { tl: "┏", tr: "┓", bl: "┗", br: "┛", h: "━", v: "┃" },
|
|
309
|
+
};
|
|
310
|
+
function drawNodes(canvas, placed, layout, transitions, nodeStyle) {
|
|
311
|
+
for (const rank of placed) {
|
|
312
|
+
for (const [index, rendered] of rank.cells.entries()) {
|
|
313
|
+
const center = rank.centers[index];
|
|
314
|
+
const cell = rendered.cell;
|
|
315
|
+
if (cell.kind === "virtual") {
|
|
316
|
+
const edge = layout.edges.find((candidate) => candidate.edgeId === cell.edgeId);
|
|
317
|
+
const taken = edge ? transitions.has(`${edge.from}->${edge.to}`) : false;
|
|
318
|
+
// Pass-through cells span the full cell height so the edge stays
|
|
319
|
+
// visually continuous across the rank row(s).
|
|
320
|
+
canvas.vline(center, rank.y, rank.y + cellHeight(nodeStyle) - 1, taken ? "taken" : "dim");
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
const status = rendered.status ?? "queued";
|
|
324
|
+
const startX = center - Math.floor(rendered.width / 2);
|
|
325
|
+
if (nodeStyle === "box") {
|
|
326
|
+
drawNodeBox(canvas, startX, rank.y, rendered, status);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
canvas.put(startX, rank.y, STATUS_GLYPHS[status], STATUS_STYLES[status]);
|
|
330
|
+
canvas.text(startX + 2, rank.y, rendered.text, status === "queued" ? "dim" : "plain");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* A bordered node cell. Edge geometry keeps lines outside the border rows,
|
|
337
|
+
* so borders stay unbroken; the active node gets a heavy border so the
|
|
338
|
+
* current position stands out.
|
|
339
|
+
*/
|
|
340
|
+
function drawNodeBox(canvas, startX, y, rendered, status) {
|
|
341
|
+
const chars = status === "active" ? BOX_CHARS.heavy : BOX_CHARS.light;
|
|
342
|
+
const style = STATUS_STYLES[status];
|
|
343
|
+
const innerWidth = rendered.width - 2;
|
|
344
|
+
canvas.text(startX, y, `${chars.tl}${chars.h.repeat(innerWidth)}${chars.tr}`, style);
|
|
345
|
+
canvas.text(startX, y + 1, chars.v, style);
|
|
346
|
+
canvas.put(startX + 2, y + 1, STATUS_GLYPHS[status], style);
|
|
347
|
+
canvas.text(startX + 4, y + 1, rendered.text, status === "queued" ? "dim" : "plain");
|
|
348
|
+
canvas.text(startX + rendered.width - 1, y + 1, chars.v, style);
|
|
349
|
+
canvas.text(startX, y + 2, `${chars.bl}${chars.h.repeat(innerWidth)}${chars.br}`, style);
|
|
350
|
+
}
|
|
351
|
+
function edgeStyle(pairKey, transitions, activePair) {
|
|
352
|
+
if (activePair === pairKey) {
|
|
353
|
+
return "active";
|
|
354
|
+
}
|
|
355
|
+
if (transitions.has(pairKey)) {
|
|
356
|
+
return "taken";
|
|
357
|
+
}
|
|
358
|
+
return "dim";
|
|
359
|
+
}
|
|
360
|
+
function drawSegments(canvas, placed, strips, layout, transitions, activePair, graphWidth, nodeStyle, lanes) {
|
|
361
|
+
const labels = [];
|
|
362
|
+
for (let rank = 0; rank < placed.length - 1; rank += 1) {
|
|
363
|
+
const strip = strips[rank];
|
|
364
|
+
if (strip.segments.length === 0) {
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
const top = placed[rank];
|
|
368
|
+
const bottom = placed[rank + 1];
|
|
369
|
+
// Forward lines start right below the source cell, cross any back-edge
|
|
370
|
+
// lane rows (as ┼ crossings), run their strip tracks, then cross the
|
|
371
|
+
// entry lanes to the arrow row directly above the target cell.
|
|
372
|
+
const stubTop = top.y + cellHeight(nodeStyle);
|
|
373
|
+
const stripTop = stubTop + lanes.below(rank).length;
|
|
374
|
+
const arrowY = bottom.y - 1;
|
|
375
|
+
const stripBottom = arrowY - 1 - lanes.above(rank + 1).length;
|
|
376
|
+
for (const segment of strip.segments) {
|
|
377
|
+
const edge = layout.edges.find((candidate) => candidate.edgeId === segment.edgeId);
|
|
378
|
+
if (!edge) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const style = edgeStyle(`${edge.from}->${edge.to}`, transitions, activePair);
|
|
382
|
+
const { fromX, toX } = segment;
|
|
383
|
+
const trackY = stripTop + segment.track;
|
|
384
|
+
if (fromX === toX) {
|
|
385
|
+
canvas.vline(fromX, stubTop, arrowY, style);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
if (trackY > stubTop) {
|
|
389
|
+
canvas.vline(fromX, stubTop, trackY - 1, style);
|
|
390
|
+
}
|
|
391
|
+
canvas.put(fromX, trackY, toX > fromX ? "└" : "┘", style);
|
|
392
|
+
canvas.hline(trackY, Math.min(fromX, toX) + 1, Math.max(fromX, toX) - 1, style);
|
|
393
|
+
canvas.put(toX, trackY, toX > fromX ? "┐" : "┌", style);
|
|
394
|
+
if (arrowY > trackY) {
|
|
395
|
+
canvas.vline(toX, trackY + 1, arrowY, style);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (segment.targetIsNode) {
|
|
399
|
+
canvas.put(toX, arrowY, "▼", style);
|
|
400
|
+
}
|
|
401
|
+
if (segment.label !== undefined) {
|
|
402
|
+
labels.push({
|
|
403
|
+
text: segment.label,
|
|
404
|
+
style,
|
|
405
|
+
fromX,
|
|
406
|
+
toX,
|
|
407
|
+
trackY,
|
|
408
|
+
labelRow: Math.min(stripTop + strip.trackCount, stripBottom),
|
|
409
|
+
graphWidth,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return labels;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Place a branch label. Labels are drawn after every line is on the canvas,
|
|
418
|
+
* so a spot that is free now stays free: first try writing over the
|
|
419
|
+
* segment's own horizontal run (only plain `─` cells may be replaced), then
|
|
420
|
+
* the strip's reserved label row beside the descending line, trying the
|
|
421
|
+
* side facing the graph center first.
|
|
422
|
+
*/
|
|
423
|
+
function drawSegmentLabel(canvas, label) {
|
|
424
|
+
const { text, style, fromX, toX, trackY, labelRow, graphWidth } = label;
|
|
425
|
+
const padded = ` ${text} `;
|
|
426
|
+
if (fromX !== toX) {
|
|
427
|
+
const runStart = Math.min(fromX, toX) + 1;
|
|
428
|
+
const runEnd = Math.max(fromX, toX) - 1;
|
|
429
|
+
const center = Math.floor((runStart + runEnd) / 2) - Math.floor(padded.length / 2);
|
|
430
|
+
if (runEnd - runStart + 1 >= padded.length + 2 &&
|
|
431
|
+
canvas.textOverRun(center, trackY, padded, style)) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const candidates = toX >= Math.floor(graphWidth / 2)
|
|
436
|
+
? [
|
|
437
|
+
[toX - text.length - 1, labelRow],
|
|
438
|
+
[toX + 2, labelRow],
|
|
439
|
+
]
|
|
440
|
+
: [
|
|
441
|
+
[toX + 2, labelRow],
|
|
442
|
+
[toX - text.length - 1, labelRow],
|
|
443
|
+
];
|
|
444
|
+
for (const [x, y] of candidates) {
|
|
445
|
+
if (canvas.textIfEmpty(x, y, text, style)) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// Last resort: beside the source corner on the track row.
|
|
450
|
+
canvas.textIfEmpty(fromX + 2, trackY, text, style);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Each back edge leaves its source cell downward into its own lane row,
|
|
454
|
+
* runs right to a private gutter column, climbs the gutter, and re-enters
|
|
455
|
+
* through its target's entry lane and arrow row from above. Every lane row
|
|
456
|
+
* and gutter column is exclusive to one edge, so loop lines can only ever
|
|
457
|
+
* cross other lines (merging into ┼), never run along them.
|
|
458
|
+
*/
|
|
459
|
+
function drawBackEdges(canvas, placed, layout, transitions, graphWidth, nodeStyle, lanes) {
|
|
460
|
+
let gutterX = graphWidth + GUTTER_GAP;
|
|
461
|
+
for (const edge of lanes.edges) {
|
|
462
|
+
const fromRank = layout.rankOfNode.get(edge.from);
|
|
463
|
+
const toRank = layout.rankOfNode.get(edge.to);
|
|
464
|
+
if (fromRank === undefined || toRank === undefined) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
const from = placed[fromRank];
|
|
468
|
+
const to = placed[toRank];
|
|
469
|
+
const exit = cellAnchor(from, edge.from, lanes.below(fromRank), edge);
|
|
470
|
+
const entry = cellAnchor(to, edge.to, lanes.above(toRank), edge);
|
|
471
|
+
if (!exit || !entry) {
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
const style = transitions.has(`${edge.from}->${edge.to}`) ? "taken" : "back";
|
|
475
|
+
const exitLaneY = from.y + cellHeight(nodeStyle) + exit.lane;
|
|
476
|
+
const aboveCount = lanes.above(toRank).length;
|
|
477
|
+
const arrowY = to.y - 1;
|
|
478
|
+
const entryLaneY = arrowY - aboveCount + entry.lane;
|
|
479
|
+
// Downward stub out of the source cell, then right along the exit lane.
|
|
480
|
+
if (exitLaneY > from.y + cellHeight(nodeStyle)) {
|
|
481
|
+
canvas.vline(exit.x, from.y + cellHeight(nodeStyle), exitLaneY - 1, style);
|
|
482
|
+
}
|
|
483
|
+
canvas.put(exit.x, exitLaneY, "└", style);
|
|
484
|
+
canvas.hline(exitLaneY, exit.x + 1, gutterX - 1, style);
|
|
485
|
+
canvas.put(gutterX, exitLaneY, "┘", style);
|
|
486
|
+
// Up the gutter, then left along the entry lane into the target.
|
|
487
|
+
canvas.put(gutterX, entryLaneY, "┐", style);
|
|
488
|
+
if (exitLaneY - entryLaneY > 1) {
|
|
489
|
+
canvas.vline(gutterX, entryLaneY + 1, exitLaneY - 1, style);
|
|
490
|
+
}
|
|
491
|
+
canvas.hline(entryLaneY, entry.x + 1, gutterX - 1, style);
|
|
492
|
+
canvas.put(entry.x, entryLaneY, "┌", style);
|
|
493
|
+
if (arrowY - entryLaneY > 1) {
|
|
494
|
+
canvas.vline(entry.x, entryLaneY + 1, arrowY - 1, style);
|
|
495
|
+
}
|
|
496
|
+
canvas.put(entry.x, arrowY, "▼", style);
|
|
497
|
+
if (edge.label !== undefined) {
|
|
498
|
+
canvas.text(gutterX + 2, entryLaneY, edge.label, style);
|
|
499
|
+
}
|
|
500
|
+
// Reserve horizontal room for this gutter and its label before the next.
|
|
501
|
+
gutterX += 2 + (edge.label === undefined ? 0 : edge.label.length + 1);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Where a back edge touches a node cell: offset right of center so the
|
|
506
|
+
* stub can never collide with forward-edge lines at the center column,
|
|
507
|
+
* clamped inside the cell.
|
|
508
|
+
*/
|
|
509
|
+
function cellAnchor(rank, nodeId, laneEdges, edge) {
|
|
510
|
+
const index = rank.cells.findIndex((cell) => cell.cell.kind === "node" && cell.cell.nodeId === nodeId);
|
|
511
|
+
const lane = laneEdges.findIndex((candidate) => candidate.edgeId === edge.edgeId);
|
|
512
|
+
if (index === -1 || lane === -1) {
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
515
|
+
const cell = rank.cells[index];
|
|
516
|
+
const center = rank.centers[index];
|
|
517
|
+
const rightmost = center + Math.floor(cell.width / 2) - 1;
|
|
518
|
+
return { x: Math.min(center + 2 + lane * 2, rightmost), lane };
|
|
519
|
+
}
|
|
520
|
+
//# sourceMappingURL=graph-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-render.js","sourceRoot":"","sources":["../../src/render/graph-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { WorkflowDefinitionSnapshot } from "../workflows/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Graph layout for the terminal viewer, ported from the acpx replay viewer's
|
|
4
|
+
* view-model (expand switch edges, classify back edges via shortest levels,
|
|
5
|
+
* longest-path layering with terminal tail pull-down, barycenter ordering).
|
|
6
|
+
* The one addition is virtual pass-through cells so every forward edge spans
|
|
7
|
+
* exactly one rank, which keeps text routing local to each rank gap.
|
|
8
|
+
*/
|
|
9
|
+
export type GraphEdge = {
|
|
10
|
+
edgeId: string;
|
|
11
|
+
from: string;
|
|
12
|
+
to: string;
|
|
13
|
+
/** Switch case key for labelled branches. */
|
|
14
|
+
label?: string;
|
|
15
|
+
isBackEdge: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type GraphCell = {
|
|
18
|
+
kind: "node";
|
|
19
|
+
nodeId: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "virtual";
|
|
22
|
+
edgeId: string;
|
|
23
|
+
};
|
|
24
|
+
export type GraphSegment = {
|
|
25
|
+
edgeId: string;
|
|
26
|
+
/** Rank index the segment starts at; it ends at `rank + 1`. */
|
|
27
|
+
rank: number;
|
|
28
|
+
fromCell: number;
|
|
29
|
+
toCell: number;
|
|
30
|
+
/** Label to draw on this segment (only on the first segment of an edge). */
|
|
31
|
+
label?: string;
|
|
32
|
+
};
|
|
33
|
+
export type GraphLayout = {
|
|
34
|
+
ranks: GraphCell[][];
|
|
35
|
+
edges: GraphEdge[];
|
|
36
|
+
/** Forward-edge segments between adjacent ranks. */
|
|
37
|
+
segments: GraphSegment[];
|
|
38
|
+
/** Rank index of every real node. */
|
|
39
|
+
rankOfNode: Map<string, number>;
|
|
40
|
+
};
|
|
41
|
+
export declare function expandEdges(snapshot: WorkflowDefinitionSnapshot): GraphEdge[];
|
|
42
|
+
/**
|
|
43
|
+
* Build ranks with virtual pass-through cells so every forward edge connects
|
|
44
|
+
* adjacent ranks, then order cells within ranks by neighbor barycenter.
|
|
45
|
+
*/
|
|
46
|
+
export declare function layoutGraph(snapshot: WorkflowDefinitionSnapshot): GraphLayout;
|