Skip to content

Commit ef121a7

Browse files
authored
Merge pull request #764 from Pipelex/release/v0.20.13
Release v0.20.13
2 parents b37f20d + 58049aa commit ef121a7

23 files changed

Lines changed: 148 additions & 1573 deletions

.badges/tests.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schemaVersion": 1,
33
"label": "tests",
4-
"message": "4032",
4+
"message": "4001",
55
"color": "blue",
66
"cacheSeconds": 300
77
}

.pipelex/pipelex.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ error_stack_traces = true
4848
graphspec_json = true
4949
mermaidflow_mmd = true
5050
mermaidflow_html = true
51-
reactflow_viewspec = true
5251
reactflow_html = true
5352

5453
[pipelex.pipeline_execution_config.graph_config.reactflow_config]

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [v0.20.13] - 2026-03-16
4+
5+
### Removed
6+
7+
- Remove unused `ViewSpec` class and related code from graph/reactflow — dead code that was no longer referenced.
8+
39
## [v0.20.12] - 2026-03-16
410

511
### Fixed

docs/under-the-hood/execution-graph-tracing.md

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ graph_spec = await dry_run_pipe_with_graph(pipe)
8484
| `graphspec_json` | `_graphspec.json` | Canonical graph representation |
8585
| `mermaidflow_mmd` | `_mermaid.mmd` | Mermaid flowchart code |
8686
| `mermaidflow_html` | `_mermaid.html` | Standalone Mermaid viewer |
87-
| `reactflow_viewspec` | `_viewspec.json` | ViewSpec for ReactFlow |
8887
| `reactflow_html` | `_reactflow.html` | Interactive ReactFlow viewer |
8988

9089
---
@@ -132,11 +131,9 @@ flowchart TB
132131
subgraph RENDER["Renderers"]
133132
direction TB
134133
MF["MermaidflowFactory"]
135-
RF["ViewSpec Transformer"]
136-
HTML1["Mermaid HTML"]
137-
HTML2["ReactFlow HTML"]
138-
MF --> HTML1
139-
RF --> HTML2
134+
RF["ReactFlow HTML Generator"]
135+
MF --> HTML1["Mermaid HTML"]
136+
RF --> HTML2["ReactFlow HTML"]
140137
end
141138
142139
JOB --> CTX
@@ -363,27 +360,9 @@ print(mermaidflow.mermaid_code)
363360
- Stuff nodes (data items) rendered as stadium shapes
364361
- DATA edges connect producers → stuff → consumers
365362

366-
### ViewSpec (ReactFlow)
363+
### ReactFlow HTML
367364

368-
Transforms GraphSpec into a viewer-oriented model:
369-
370-
```python
371-
from pipelex.graph.reactflow.viewspec_transformer import graphspec_to_viewspec
372-
373-
analysis = GraphAnalysis.from_graphspec(graph_spec)
374-
viewspec = graphspec_to_viewspec(
375-
graph_spec,
376-
analysis,
377-
options={"show_data_edges": True},
378-
)
379-
```
380-
381-
ViewSpec provides:
382-
383-
- `ViewNode` with UI metadata (badges, classes, inspector data)
384-
- `ViewEdge` with ReactFlow properties (animated, hidden)
385-
- `ViewIndex` for fast client-side lookups
386-
- Layout configuration for Dagre
365+
ReactFlow HTML is generated directly from GraphSpec — no intermediate ViewSpec layer. The HTML generator embeds GraphSpec as JSON and the client-side JavaScript handles dataflow analysis, layout, and rendering.
387366

388367
---
389368

@@ -405,7 +384,6 @@ error_stack_traces = true # Include full stack traces
405384
graphspec_json = true # Generate GraphSpec JSON
406385
mermaidflow_mmd = true # Generate Mermaid code
407386
mermaidflow_html = true # Generate Mermaid HTML
408-
reactflow_viewspec = true # Generate ViewSpec JSON
409387
reactflow_html = true # Generate ReactFlow HTML
410388
```
411389

@@ -480,7 +458,7 @@ validate_graphspec(graph_spec)
480458
| `GraphSpec.to_json()` | Serialize to JSON string |
481459
| `GraphAnalysis.from_graphspec(g)` | Pre-compute analysis |
482460
| `MermaidflowFactory.make_from_graphspec(...)` | Generate Mermaid |
483-
| `graphspec_to_viewspec(g, analysis)` | Generate ViewSpec |
461+
| `generate_reactflow_html(graphspec, config)` | Generate ReactFlow HTML |
484462
| `generate_graph_outputs(g, config, pipe_code)` | Generate all outputs |
485463

486464
---

pipelex/cli/agent_cli/commands/validate/bundle_cmd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def validate_bundle_cmd(
4949
] = None,
5050
view: Annotated[
5151
bool,
52-
typer.Option("--view", help="On successful bundle validation, include a ViewSpec (structured JSON for graph rendering) in the output"),
52+
typer.Option("--view", help="On successful bundle validation, include a GraphSpec (structured JSON for graph rendering) in the output"),
5353
] = False,
5454
library_dir: Annotated[
5555
list[str] | None,
@@ -147,7 +147,7 @@ def validate_bundle_cmd(
147147
except Exception as exc:
148148
agent_error(f"Graph generation failed: {exc}", type(exc).__name__, cause=exc)
149149

150-
# Generate view (ViewSpec JSON) if requested and validation succeeded
150+
# Generate view (GraphSpec JSON) if requested and validation succeeded
151151
if view:
152152
try:
153153
view_result = asyncio.run(

pipelex/graph/graph_config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class GraphsInclusionConfig(ConfigModel):
1818
graphspec_json: bool
1919
mermaidflow_mmd: bool
2020
mermaidflow_html: bool
21-
reactflow_viewspec: bool
2221
reactflow_html: bool
2322

2423

pipelex/graph/graph_factory.py

Lines changed: 23 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@
1111
from pydantic import BaseModel
1212

1313
from pipelex import log
14-
from pipelex.graph.graph_analysis import GraphAnalysis
1514
from pipelex.graph.mermaidflow.mermaid_html import render_mermaid_html_async, render_mermaid_html_with_data_async
1615
from pipelex.graph.mermaidflow.mermaidflow_factory import MermaidflowFactory
1716
from pipelex.graph.mermaidflow.stuff_collector import collect_stuff_data_html, collect_stuff_data_text
1817
from pipelex.graph.reactflow.reactflow_html import generate_reactflow_html_async
19-
from pipelex.graph.reactflow.viewspec import LayoutSpec
20-
from pipelex.graph.reactflow.viewspec_transformer import graphspec_to_viewspec
2118
from pipelex.tools.misc.string_utils import snake_to_title_case
2219

2320
if TYPE_CHECKING:
@@ -37,14 +34,12 @@ class GraphOutputs(BaseModel):
3734
graphspec_json: The GraphSpec serialized as JSON.
3835
mermaidflow_mmd: Mermaidflow view as Mermaid flowchart code.
3936
mermaidflow_html: Mermaidflow view as standalone HTML page.
40-
reactflow_viewspec: The ViewSpec serialized as JSON for ReactFlow rendering.
4137
reactflow_html: ReactFlow interactive graph as standalone HTML page.
4238
"""
4339

4440
graphspec_json: str | None = None
4541
mermaidflow_mmd: str | None = None
4642
mermaidflow_html: str | None = None
47-
reactflow_viewspec: str | None = None
4843
reactflow_html: str | None = None
4944

5045

@@ -64,15 +59,14 @@ async def generate_graph_outputs(
6459
This can generate:
6560
- GraphSpec JSON: The canonical graph representation
6661
- Mermaidflow view: Data flow with controller subgraphs (Mermaid)
67-
- ReactFlow ViewSpec: JSON for ReactFlow rendering
6862
- ReactFlow HTML: Interactive graph viewer
6963
7064
Args:
7165
graph_spec: The GraphSpec to render.
7266
graph_config: Configuration controlling which outputs to generate and data inclusion.
7367
pipe_code: The pipe code, used to derive the HTML page title when title is not provided.
7468
title: Explicit HTML page title. When provided, overrides the auto-derived title from pipe_code.
75-
direction: Flowchart direction for Mermaid diagrams. When None, uses graph_config.mermaid_config.direction.
69+
direction: Flowchart direction override for both Mermaid and ReactFlow outputs. When None, each renderer uses its own config default.
7670
include_subgraphs: Whether to render controller hierarchy as subgraphs in Mermaid output.
7771
7872
Returns:
@@ -84,7 +78,6 @@ async def generate_graph_outputs(
8478
graphspec_json: str | None = None
8579
mermaidflow_mmd: str | None = None
8680
mermaidflow_html: str | None = None
87-
reactflow_viewspec: str | None = None
8881
reactflow_html: str | None = None
8982

9083
# Generate GraphSpec JSON
@@ -121,47 +114,34 @@ async def generate_graph_outputs(
121114
else:
122115
mermaidflow_html = await render_mermaid_html_async(mermaidflow.mermaid_code, title=page_title, theme=mermaid_theme)
123116

124-
# Generate ReactFlow outputs
125-
if inclusion.reactflow_viewspec or inclusion.reactflow_html:
126-
analysis = GraphAnalysis.from_graphspec(graph_spec)
127-
rf_config = graph_config.reactflow_config
128-
effective_rf_direction = direction or rf_config.layout_direction
129-
layout = LayoutSpec(
130-
direction=effective_rf_direction,
131-
nodesep=rf_config.nodesep,
132-
ranksep=rf_config.ranksep,
117+
# Generate ReactFlow HTML
118+
if inclusion.reactflow_html:
119+
# Collect stuff data in alternate formats if configured
120+
rf_stuff_data_text: dict[str, str] | None = None
121+
rf_stuff_data_html: dict[str, str] | None = None
122+
if graph_config.data_inclusion.stuff_text_content:
123+
log.verbose("Collecting stuff data text for graph_spec")
124+
rf_stuff_data_text = collect_stuff_data_text(graph_spec)
125+
else:
126+
log.verbose("No stuff data text to collect for graph_spec")
127+
if graph_config.data_inclusion.stuff_html_content:
128+
rf_stuff_data_html = collect_stuff_data_html(graph_spec)
129+
130+
effective_rf_config = graph_config.reactflow_config
131+
if direction is not None:
132+
effective_rf_config = effective_rf_config.model_copy(update={"layout_direction": direction})
133+
reactflow_html = await generate_reactflow_html_async(
134+
graph_spec,
135+
effective_rf_config,
136+
stuff_data_text=rf_stuff_data_text,
137+
stuff_data_html=rf_stuff_data_html,
138+
title=page_title,
133139
)
134-
viewspec = graphspec_to_viewspec(graph_spec, analysis, layout=layout)
135-
136-
if inclusion.reactflow_viewspec:
137-
reactflow_viewspec = viewspec.model_dump_json(indent=2)
138-
139-
if inclusion.reactflow_html:
140-
# Collect stuff data in alternate formats if configured
141-
rf_stuff_data_text: dict[str, str] | None = None
142-
rf_stuff_data_html: dict[str, str] | None = None
143-
if graph_config.data_inclusion.stuff_text_content:
144-
log.verbose("Collecting stuff data text for graph_spec")
145-
rf_stuff_data_text = collect_stuff_data_text(graph_spec)
146-
else:
147-
log.verbose("No stuff data text to collect for graph_spec")
148-
if graph_config.data_inclusion.stuff_html_content:
149-
rf_stuff_data_html = collect_stuff_data_html(graph_spec)
150-
151-
reactflow_html = await generate_reactflow_html_async(
152-
viewspec,
153-
graph_config.reactflow_config,
154-
graphspec=graph_spec,
155-
stuff_data_text=rf_stuff_data_text,
156-
stuff_data_html=rf_stuff_data_html,
157-
title=page_title,
158-
)
159140

160141
return GraphOutputs(
161142
graphspec_json=graphspec_json,
162143
mermaidflow_mmd=mermaidflow_mmd,
163144
mermaidflow_html=mermaidflow_html,
164-
reactflow_viewspec=reactflow_viewspec,
165145
reactflow_html=reactflow_html,
166146
)
167147

@@ -205,12 +185,6 @@ def save_graph_outputs_to_dir(
205185
saved_files["mermaidflow_html"] = file_path
206186
log.verbose(f"Mermaidflow HTML saved to: {file_path}")
207187

208-
if graph_outputs.reactflow_viewspec is not None:
209-
file_path = output_dir / "viewspec.json"
210-
file_path.write_text(graph_outputs.reactflow_viewspec, encoding="utf-8")
211-
saved_files["reactflow_viewspec"] = file_path
212-
log.verbose(f"ReactFlow ViewSpec saved to: {file_path}")
213-
214188
if graph_outputs.reactflow_html is not None:
215189
file_path = output_dir / "reactflow.html"
216190
file_path.write_text(graph_outputs.reactflow_html, encoding="utf-8")

pipelex/graph/graph_rendering.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111
from pipelex.config import get_config
1212
from pipelex.core.interpreter.exceptions import PipelexInterpreterError
1313
from pipelex.core.interpreter.interpreter import PipelexInterpreter
14-
from pipelex.graph.graph_analysis import GraphAnalysis
1514
from pipelex.graph.graph_config import GraphConfig
1615
from pipelex.graph.graph_factory import GraphOutputs, generate_graph_outputs, save_graph_outputs_to_dir
1716
from pipelex.graph.graphspec import GraphSpec
18-
from pipelex.graph.reactflow.viewspec import LayoutSpec
19-
from pipelex.graph.reactflow.viewspec_transformer import graphspec_to_viewspec
2017
from pipelex.pipe_run.pipe_run_mode import PipeRunMode
2118
from pipelex.pipeline.runner import PipelexRunner
2219
from pipelex.tools.misc.chart_utils import FlowchartDirection
@@ -89,7 +86,6 @@ async def render_graph_from_spec(
8986
"graphspec_json": False,
9087
"mermaidflow_mmd": False,
9188
"mermaidflow_html": include_mermaidflow,
92-
"reactflow_viewspec": False,
9389
"reactflow_html": include_reactflow,
9490
}
9591
),
@@ -246,15 +242,14 @@ async def generate_graph_for_bundle(
246242
}
247243

248244

249-
# TODO: refactor to do only one dry run and generate both graph and ViewSpec
250245
async def generate_view_for_bundle(
251246
bundle_path: Path,
252247
library_dirs: list[str] | None = None,
253248
direction: FlowchartDirection | None = None,
254249
) -> dict[str, Any]:
255-
"""Generate a ViewSpec for a bundle via dry-run pipeline execution.
250+
"""Generate a GraphSpec for a bundle via dry-run pipeline execution.
256251
257-
Returns structured JSON data (ViewSpec) suitable for client-side rendering,
252+
Returns structured JSON data (GraphSpec) suitable for client-side rendering,
258253
without writing any files to disk.
259254
260255
Args:
@@ -263,7 +258,7 @@ async def generate_view_for_bundle(
263258
direction: Flowchart layout direction (default: None, uses config default).
264259
265260
Returns:
266-
Dictionary with viewspec (JSON-serializable dict), pipe_code, and direction.
261+
Dictionary with graphspec (JSON-serializable dict), pipe_code, and direction.
267262
268263
Raises:
269264
PipelexInterpreterError: If bundle parsing fails or main_pipe is missing.
@@ -279,16 +274,7 @@ async def generate_view_for_bundle(
279274
rf_config = execution_config.graph_config.reactflow_config
280275
effective_direction = direction or rf_config.layout_direction
281276

282-
analysis = GraphAnalysis.from_graphspec(graph_spec)
283-
layout = LayoutSpec(
284-
direction=effective_direction,
285-
nodesep=rf_config.nodesep,
286-
ranksep=rf_config.ranksep,
287-
)
288-
viewspec = graphspec_to_viewspec(graph_spec, analysis, layout=layout)
289-
290277
return {
291-
"viewspec": viewspec.model_dump(mode="json"),
292278
"graphspec": graph_spec.model_dump(mode="json", by_alias=True),
293279
"pipe_code": pipe_code,
294280
"direction": str(effective_direction) if effective_direction else None,

0 commit comments

Comments
 (0)