feat: add visual builder + workspace mode to Burr UI#687
feat: add visual builder + workspace mode to Burr UI#687andreahlert wants to merge 12 commits intoapache:mainfrom
Conversation
|
@andreahlert I can't get this to run locally -- did you commit everything? otherwise see the CI failures. |
|
Also need some example to load to help someone get started. |
|
Thanks for reviewing. Didn't have the time to check it properly, I'll do it as soon as possible. Target: 03-30-2026 |
|
Thanks for trying it out. Two things:
Working on both now. |
JiwaniZakir
left a comment
There was a problem hiding this comment.
In run.py, the shutdown sequence in lifespan calls await workspace.cleanup_processes() directly before await backend.lifespan(app).__anext__(), but there's no try/finally wrapping these calls. If cleanup_processes() raises an exception, the backend's own cleanup will be silently skipped, potentially leaking database connections or other resources. The backend shutdown should be guarded with a try/finally block regardless of what happens in workspace cleanup.
Additionally, supports_workspace=True is hardcoded unconditionally in _get_app_spec() — this means the UI will always advertise workspace support even if the feature is disabled or broken at runtime. This should be derived from a config flag or at least check that the workspace module initialized successfully, similar to how is_snapshotting_backend and is_annotations_backend are computed from the actual backend capabilities.
The _validate_workspace allowlist approach in workspace.py is a reasonable security boundary, but _read_links() is called on every file-browsing request with no caching. If the links file is read from disk on each API call under load, this could become a bottleneck — a short-lived in-process cache or memoization with invalidation on write would be worth considering.
elijahbenizzy
left a comment
There was a problem hiding this comment.
Played around some -- looking great! Node types should probably have specific implementations but I think this is a good start to put out there.
Adds a low-code visual builder with split-view Monaco editor, workspace file browsing, and project persistence. Builder features: - 9 node types (Action, Input, Result, LLM Call, API Call, Code, Streaming, Loop, Router) with specialized property editors - Inline + buttons on edges for inserting nodes (Activepieces-style) - Recursive layout algorithm supporting loop arcs and router fan-out - Monaco Editor with multi-file code generation (actions.py, app.py, run.py, requirements.txt) - Bidirectional sync between graph and code - Searchable node type picker with categories - File menu with save/load projects, Ctrl+S support - Undo/redo (50-state history), copy/paste, delete shortcuts - Code generation with sanitized identifiers and proper imports Workspace features: - Backend router for file browsing, code viewing, script execution (SSE streaming), process management, and workspace-project linking - Builder project persistence in ~/.burr/builder_projects/ - Path traversal protection with workspace validation New dependencies (all MIT, ASF Category A): - @monaco-editor/react - @tanstack/react-query - @xyflow/react - react-joyride
- Remove unused imports/variables flagged by ESLint - Replace regex literal with RegExp constructor to avoid no-control-regex - Format workspace.py with black and isort
- Replace `as any` with proper types where possible - Add eslint-disable comments for icon type maps (heroicons ForwardRef) - Remove unused `id` from edge component destructures - Remove unused `langMap` variable from BuilderView
This takes work from @jaeyow and apache#572. Adds a drag-and-drop graph editor for designing Burr application graphs visually and exporting as Python code or JSON. Key changes: - New /graph-builder route with full visual editor (ReactFlow v12) - Migrate existing GraphView from reactflow v11 to @xyflow/react v12 - Remove reactflow and @tisoap/react-flow-smart-edge dependencies - Per-node async/streaming toggles matching Burr's 4 action variants - Python code generation with correct decorators and signatures - 3 pre-built example graphs (MultiModal Chatbot, CRAG, Streaming) - localStorage auto-save/restore of graph state - Empty-state onboarding overlay and structured help sidebar - Fix appcontainer layout for full-height content
Python (workspace.py): - Module-level docstring describing all capabilities - Docstrings on all Pydantic models, endpoints, and helper functions - Documented security functions with Args/Returns/Raises TypeScript: - JSDoc on all exported types in builderTypes, codeGenerator, codeParser - JSDoc on all tree operation functions in treeUtils - JSDoc on layout algorithm functions in flowLayout - JSDoc on useBuilderState hook
Remove the legacy react-query v3 package and standardize on @tanstack/react-query v5 across all components. This fixes the "No QueryClient set" error in BuilderView which was caused by two separate QueryClient providers from different packages.
Wrap workspace.cleanup_processes() in try/finally so backend shutdown always runs even if process cleanup fails. Derive supports_workspace from workspace.is_available() instead of hardcoding True. Add in-process cache to _read_links() to avoid disk reads on every file-browsing request.
898f6be to
0fff68f
Compare
|
All review feedback addressed. Rebased clean on main, no conflicts. @JiwaniZakir your three points: @skrawcz docstrings on every function/class in workspace.py, including the inner ones. Examples were already in from the graph-builder merge. @elijahbenizzy opened #735 to track the node type implementations as a follow-up. Agreed it's fine for the initial merge. Ready for re-review whenever you get a chance. |


Building on #667 (Graph Builder by @skrawcz), this adds a workspace mode and significantly enhanced builder that turns Burr's UI into a development environment.
What's new
Visual Builder (enhanced)
Monaco Editor (split view)
Project save/load
Workspace integration
Other improvements
Screenshots
Builder with nodes and generated code

Node editor with LLM Call configuration

Searchable node type picker

Technical details
Backend (Python)
burr/tracking/server/workspace.py: new APIRouter with endpoints for file tree, file content, script execution (SSE), process management, workspace links, and builder project persistencerun.pyto mount workspace router,schema.pyto addsupports_workspaceFrontend (~6,700 new lines)
utils/: builderTypes, codeGenerator (9 node types + multi-file), codeParser (bidirectional sync), flowLayout (recursive layout), treeUtils (immutable tree ops), stateFlowhooks/useBuilderState.ts: tree-based state with undo/redo, keyboard shortcuts, save/loadbuilder/: BuilderView (split layout), BuilderGraph (ReactFlow with custom node/edge types), NodeEditor, NodeTypePicker (portal-based), 4 node components, 5 edge components with inline + buttonsworkspace/: FileExplorer, CodeViewer, RunTerminal, WorkspaceSelectorproject/: ProjectWorkspaceView, ActivityBar, SidePanel, TabBar, TrackingSidePanelDependencies added
@monaco-editor/react(MIT)@tanstack/react-query(MIT)@xyflow/react(MIT)react-joyride(MIT)All MIT license, ASF Category A compatible.
How I tested
npx tsc --noEmitzero errorsChecklist