# fai_studio_flow_editor Swappable in-Studio flow editor for the Ch∆In. Hosts a three-tab editing surface on top of one in-memory flow YAML: - **Graph** — drag-and-drop WYSIWYG canvas of step nodes and their input / output ports, edges derived live from `$ref` expressions in the YAML. - **Text** — full-screen YAML editor with line numbers and syntax highlighting, anchored at the top of the viewport. - **Run** — inputs form, Start button, live step-progress list driven by the host's event stream, typed outputs once the run resolves. The package is intentionally host-agnostic. Studio depends on it via a `git: ref: main` pubspec entry; replacing the editor is one pubspec change and a rebuild. ## Public surface ```dart import 'package:fai_studio_flow_editor/fai_studio_flow_editor.dart'; FlowEditorPage( initialFlowName: String?, // preload this flow locale: FlowEditorLocale, // en | de runDriver: FlowRunDriver?, // host-supplied hub bridge availableCapabilities: List, // for the Add-step picker ) ``` Host implements `FlowRunDriver` to bridge the editor's `runFlow` + `events` calls to whatever talks to the hub: ```dart abstract class FlowRunDriver { Future> runFlow({ required String flowName, required Map textInputs, required Map fileInputs, required Map fileMimes, }); Stream events(); } ``` Event types: `StepStarted`, `StepCompleted`, `StepFailed`, `StepAwaitingApproval`. Output types: `FlowOutputText`, `FlowOutputJson`, `FlowOutputBytes`. ## Source-of-truth model YAML text is the canonical state. The graph view derives a `FlowGraph` object from the YAML on every change (debounced 350 ms). Graph edits emit fresh YAML into the shared `CodeController` via `FlowGraph.toYaml()`. The two tabs cannot fall out of sync because both observe the same `FlowEditorController`. Node positions are the one piece NOT in the YAML — they live in a per-flow sidecar JSON file at `~/.fai/data/flows/.layout/.json`. This keeps the YAML byte-stable for the hub's audit log and avoids spurious diffs in version control. ## Behaviour - File browser (left, 240 px) lists `*.yaml` in `~/.fai/data/flows/` with a FLOWS header + refresh icon. - Graph tab: InteractiveViewer with pan + zoom; drag a node body to reposition; drag an output port → drop on an input port to create a `$source.field` reference; click a node to open the properties panel on the right. - Text tab: YAML with syntax highlighting, top-aligned via `expands: true` on the underlying CodeField. - Run tab: inputs form with text fields + file picks, Start button, live step list driven by the driver's event stream, typed outputs once the run resolves. - Save writes directly to disk via `dart:io`; the hub picks up the change on its next `ListFlows` / `RunSavedFlow` call. Cmd+S / Ctrl+S — save. Cmd+Enter / Ctrl+Enter — jump to the Run tab. ## Folder layout ``` lib/ ├── fai_studio_flow_editor.dart exports public API └── src/ ├── editor_controller.dart shared state + reparse loop ├── flow_editor_page.dart host scaffolding, tabs ├── l10n.dart EN/DE strings ├── run_driver.dart host bridge interface ├── tokens.dart spacing / radius / motion ├── widgets.dart FaiEmptyState + FaiErrorBox ├── model/ │ ├── flow_graph.dart parser + serializer │ ├── auto_layout.dart topological column layout │ └── layout_store.dart sidecar JSON I/O └── widgets/ ├── flow_canvas.dart InteractiveViewer + nodes + drag ├── flow_node.dart node card primitive ├── edge_painter.dart cubic bezier edges ├── properties_panel.dart selected-step editor ├── capability_picker.dart Add-step modal └── run_tab.dart inputs + step progress + outputs ``` ## Swap it Studio depends on this package via `pubspec.yaml` git reference: ```yaml dependencies: fai_studio_flow_editor: git: url: https://git.flemming.ai/fai/studio-flow-editor ref: main ``` To use a different editor: 1. Fork this repo (or write your own from scratch). 2. Keep the `FlowEditorPage` constructor signature (`initialFlowName`, `locale`, `runDriver`, `availableCapabilities`) — that's the stable host contract. 3. Point Studio's pubspec at your fork. 4. Rebuild Studio. The contract is minimal: one page widget + a driver interface. The package brings its own tokens, its own empty/error widgets, its own l10n table, so the host doesn't have to share internals. The trade-off is visual drift if Studio's design tokens change — that's the deal you accept for a swappable module. ## Develop ```bash flutter pub get flutter analyze flutter test ``` 11 unit tests cover the parser (round-trip, edge detection, approval flagging, leading-comment preservation) and the controller (open / edit / dirty / select). ## Versioning Semantic. Major bumps when the public `FlowEditorPage` signature changes. Adding strings to `FlowEditorStrings` or events to `FlowRunEvent` is a minor bump. Patch covers visual + bug fixes inside the package. Current: **0.2.1** — first WYSIWYG release. ## License Apache-2.0. Same as the rest of the F∆I platform.