From cae5c94c4dd9fd7242985eb1a8cff07c7d5c4a48 Mon Sep 17 00:00:00 2001 From: flemming-it Date: Mon, 1 Jun 2026 01:53:29 +0200 Subject: [PATCH] docs(editor): README + version bump to 0.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expands README to describe the three-tab UX, the source-of- truth model (YAML + sidecar layout), the FlowRunDriver contract, the folder layout, and how to swap the editor. Version 0.2.0 -> 0.2.1 — picks up the live step status, the empty-graph CTA, and the fit-to-screen button added since the initial 0.2.0 commit. Signed-off-by: flemming-it --- README.md | 152 +++++++++++++++++++++++++++++++++++++-------------- pubspec.yaml | 2 +- 2 files changed, 113 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 8c7e61b..90e3e4f 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,110 @@ # fai_studio_flow_editor -Swappable inline YAML editor for F∆I Studio flows. +Swappable in-Studio flow editor for the F∆I Platform. 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'; -// Studio embeds the page as one of its destinations: FlowEditorPage( - initialFlowName: 'hello', // optional - locale: FlowEditorLocale.de, // or .en - onRun: (name) => // optional callback - HubService.instance.runSavedFlow(name: name), + initialFlowName: String?, // preload this flow + locale: FlowEditorLocale, // en | de + runDriver: FlowRunDriver?, // host-supplied hub bridge + availableCapabilities: List, // for the Add-step picker ) ``` -- **`initialFlowName`** — when set, the page loads that flow - from `~/.fai/data/flows/.yaml` on first build. Used - by Studio's Flows-page pencil → editor route push. -- **`locale`** — picks EN or DE for the editor's internal - string table. Studio passes its active locale through. -- **`onRun`** — async callback that runs the named flow - against the host hub and returns the typed outputs map. - When null, the Run button is disabled (e.g. when the - editor is embedded in a context without hub access). +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/`. -- Code field (right) ships YAML syntax highlighting via - `flutter_code_editor` + the highlight package's yaml - grammar. + `~/.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 — run. + 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 @@ -55,24 +123,18 @@ To use a different editor: 1. Fork this repo (or write your own from scratch). 2. Keep the `FlowEditorPage` constructor signature - (`initialFlowName`, `locale`, `onRun`) — that's the - stable host contract. -3. Point Studio's pubspec at your fork (or local-path - during development): - ```yaml - fai_studio_flow_editor: - git: - url: https://your-host/your/flow-editor - ref: main - ``` -4. Rebuild Studio. Done. + (`initialFlowName`, `locale`, `runDriver`, + `availableCapabilities`) — that's the stable host + contract. +3. Point Studio's pubspec at your fork. +4. Rebuild Studio. -The contract is intentionally minimal: a single page widget -with three parameters. 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. +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 @@ -82,8 +144,18 @@ flutter analyze flutter test ``` -The package's own widget tests live in `test/`. End-to-end -tests against a live hub stay in the host repo (Studio). +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 diff --git a/pubspec.yaml b/pubspec.yaml index 6ff8759..0335b71 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: fai_studio_flow_editor description: Swappable inline YAML editor for F∆I Studio flows. -version: 0.2.0 +version: 0.2.1 publish_to: 'none' repository: https://git.flemming.ai/fai/studio-flow-editor