feat(graph): expose plan tree via smithers-orchestrator/graph and add visual workflow builder sample#120
Conversation
Third-party graph tooling could already render Smithers workflows with renderFrame(), but the XML-to-plan conversion used by the runtime was only available through internal modules. That forced external consumers to either reimplement the renderer semantics themselves or depend on private paths. This change adds a minimal smithers-orchestrator/graph subpath that re-exports buildPlanTree and its related types without introducing a new graph model. It keeps the public surface small while giving visualizers and workflow builders a clean, supported way to derive the runtime plan tree from rendered XML. The accompanying docs show how to combine renderFrame() with /graph to build node-and-edge visualizations, which improves discoverability for external graph inspectors and n8n-style editors without moving that UI into Smithers itself.
Adds a self-contained graph builder sample at examples/graph-builder/ that demonstrates how to build an n8n-style visual workflow editor on top of the smithers-orchestrator/graph subpath. The sample includes: - node graph canvas with SVG edges, handles, and labeled connections - support for agent, shell, approval, parallel, loop, and branch nodes - drag-to-move node positioning - zoom controls, fit view, horizontal/vertical orientation toggle - minimap anchored to the canvas viewport - collapsible inspector panel with prompt, schema, and config editing - generated Smithers TSX code preview - runtime plan tree preview via buildPlanTree - local filesystem load/save with Smithers validation - browser file picker for importing graph JSON or workflow TSX - nearby workflow discovery for one-click import - graph-first stability model with graph JSON sidecar as source of truth - best-effort TSX import via Smithers rendering for existing workflows - disk change detection with manual reload The builder uses smithers-orchestrator/graph for plan tree extraction and renderFrame for TSX import, keeping the Smithers core API surface minimal while enabling rich external graph tooling.
The graph builder now runs entirely in the browser as a single self-contained HTML file. No server, no API calls, no Node.js runtime required. Changes: - inlined buildPlanTree and all its dependencies as pure browser JS - added client-side TSX text parser that extracts Smithers component structure (Task, Sequence, Parallel, Ralph, Branch, Approval) from uploaded TSX files - plan preview now runs buildPlanTree directly in the browser - removed all fetch calls to /api endpoints from the core editing flow - simplified file section to browser-native open/save via file picker and download - the file can be opened from file://, hosted on any static server, or embedded The server.ts file is preserved as an optional local development tool for richer features like Smithers-rendered TSX import and filesystem load/save, but it is no longer required for any core functionality.
The graph builder is fully browser-only now. The server was leftover from before the client-side buildPlanTree and TSX parser were added. No reason to keep it.
5c9d842 to
a5fc2f5
Compare
There was a problem hiding this comment.
Pull request overview
This PR exposes Smithers’ internal XML-to-plan conversion as a public subpath (smithers-orchestrator/graph) so external tooling can build accurate workflow graph visualizations, and adds docs + a browser-only example visual workflow builder demonstrating the capability.
Changes:
- Add
smithers-orchestrator/graphsubpath export forbuildPlanTree+PlanNode/RalphMeta. - Document how to use
buildPlanTree(snapshot.xml)for graph tooling and cross-link from existing runtime docs/README. - Add an in-browser visual graph builder example and a test verifying the subpath export works.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/graph/index.ts | New re-export entry point for graph-related runtime helpers/types. |
| package.json | Adds ./graph subpath export. |
| tsconfig.json | Adds path aliases for /graph in local TS resolution. |
| docs/runtime/graph.mdx | New documentation page describing /graph usage and example traversal. |
| docs/runtime/render-frame.mdx | Adds cross-reference to /graph from renderFrame docs. |
| README.md | Adds a “Graph Tooling” note pointing users to the new subpath. |
| tests/graph-subpath.test.ts | Ensures buildPlanTree is importable/functional via the new subpath. |
| examples/graph-builder/index.html | Adds a self-contained browser workflow graph builder + plan preview. |
| examples/graph-builder/README.md | Explains how to run and what the sample demonstrates. |
| PR_GRAPH_SUBPATH.md | PR notes / rationale captured in-repo. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- fix docs showing self-referential export syntax instead of consumer imports - fix textarea content escaping quotes as " entities by using a text-content-safe escape that preserves quote characters - add comment explaining intentional branch XML divergence in the builder (shows both paths at design time vs runtime which only renders the chosen one)
|
GWEN3.5-35B-A3B just reread my session with claude and came up with an even simpler way to do things This package contains:
Smithers doesn't own it, but officially recommends it. 3. Stabilize the XML format (not new types)Ensure xml structure is stable and documented. That's already mostly done - just needs better docs. ──────────────────────────────────────────────────────────────────────────────── What Smithers should NOT do for minimalism
──────────────────────────────────────────────────────────────────────────────── What external packages CAN do Any third party can build: // npm install @smithers/graphify
import { WorkflowGraph, graphFromXml } from '@smithers/graphify';
const snap = await renderFrame(workflow, ctx);
const graph: WorkflowGraph = graphFromXml(snap.xml);
// Use with React Flow / n8n / your UIThe conversion logic lives in a separate package that can evolve independently. ──────────────────────────────────────────────────────────────────────────────── Minimal Smithers surface = 3 things only
That's it for Smithers itself. ──────────────────────────────────────────────────────────────────────────────── Why this works better than adding exports ┌────────────────────────────────────────────┬──────────────────────────────────────────────────────────┬─────────────────────────────────────────────────┐ I'd recommend: external adapter package approach. It's the best balance - Smithers stays minimal but officially supported tooling exists. ──────────────────────────────────────────────────────────────────────────────── Bottom line For truly minimal Smithers:
Smithers provides: data format + docs |
I've now made this a PR that you are free to ignore or not.
I got triggered by issue 90 to showcase how it's already there and anyone can do what they want.
For ease of use i've added a simple reexport to /graph so it could be extended in the future, but graph visualisation tools imo shall live outside the workflow spec and not as part of it.
the self ontained index.html shows how easy it can be but isn't anywhere near a good production use case beyond spinning up visualisation as import/export of complex workflows requires more work and attention to detail. (loading self contained single .tsx files works well though)
Closes #90
Problem
Smithers constructs an internal scheduling DAG via
buildPlanTree()insrc/engine/scheduler.ts, but this function and its types are not exported. External consumers who want to visualize or analyze workflow graphs are left with two incomplete options:tasksarray fromrenderFrame()— no edges, no dependency information.xmltree — requires reimplementing the XML-to-plan conversion thatbuildPlanTreealready does.The actual graph that Smithers uses to schedule execution — the
PlanNodetree — is the only representation that cleanly encodes task dependencies, parallel groups, and loop semantics. But it's internal.What this PR adds
1.
smithers-orchestrator/graphsubpath exportA minimal new subpath that re-exports the existing runtime helper and types:
This is zero new implementation code — just making existing internals available through a dedicated graph-focused entry point.
Files:
src/graph/index.ts— 2 linespackage.json— 1 line (subpath export)tsconfig.json— 2 lines (path aliases)2. Documentation
Adds
docs/runtime/graph.mdxexplaining:/graphexportsrenderFrame()withbuildPlanTree()nodes[]andedges[]for external graph toolingUpdates
docs/runtime/render-frame.mdxandREADME.mdto point users at the new subpath.3. Visual workflow builder sample
Adds
examples/graph-builder/— a fully in-browser visual workflow editor that demonstrates what external tooling can build on top of/graph.The sample is a single self-contained HTML file with:
buildPlanTree(inlined as pure browser JS)No server, no API, no dependencies. Open the HTML file in any browser.
buildPlanTreeand all its dependencies are inlined as pure functions.4. Test
Adds
tests/graph-subpath.test.tsverifying thatbuildPlanTreeis importable and functional fromsmithers-orchestrator/graph.Why this approach
The issue discussion considered several options. This PR takes the most minimal path:
scheduleTasksor state-map internalsIt exposes the existing XML-to-plan conversion behind a dedicated subpath, keeping the public surface small. The sample proves the API is sufficient for building rich external graph tooling without adding anything else to Smithers core.
If external consumers prove out the need for a richer stable graph contract (e.g. explicit
nodes/edgestypes), that can be added later on the same subpath without breaking what's here.Validation
Automated
bun test tests/graph-subpath.test.ts tests/scheduler-comprehensive.test.ts tests/worktree-plan.explicit.test.ts tests/nested-ralph-bug.test.ts47 tests pass, 0 failures. Covers:
buildPlanTreeexport availabilityManual
smithers-orchestrator/graphresolves correctly viabun -efile://with zero serverexamples/simple-workflow.tsxandexamples/code-review-loop.tsxvia the in-browser text parserbuildPlanTreeentirely client-sideFiles changed
src/graph/index.tspackage.json./graphsubpath exporttsconfig.jsonsmithers/graphandsmithers-orchestrator/graphdocs/runtime/graph.mdxdocs/runtime/render-frame.mdx/graphREADME.mdtests/graph-subpath.test.tsexamples/graph-builder/index.htmlexamples/graph-builder/README.md