Skip to content

Commit 8f5c9ca

Browse files
Birfycursoragent
andauthored
Settings → Workflow graphs: canvas-first with inspector (#1440)
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> Written-by: Dev Owner: Dev Reviewer: Reviewer Fixes #1438 ## Summary **Settings → Workflow graphs** is now canvas-first with a per-node inspector panel. Select a node to edit its system prompt, role, and tools — no more wall of textareas. Manual "Add link" form preserved below inspector for edge creation (forward, loop, condition). **Workflow stage chat** reuses the normal FlyBot conversation UI (same message bubbles and spacing as Bot/group chats), replacing the previous pipeline-log card style. **Sidebar Workflows list, Hand-a-task modal, and flowchart drawer** now show visual mini-flowcharts instead of text chains like "Planner → Writer → Coder", with a unified visual language across all surfaces. ## Fixes **Hand-a-task modal overflow**: content now scrolls within max-height ≤ viewport, Cancel/Confirm footer is sticky and always visible. **Flowchart drawer**: defaults to showing the graph collapsed; system prompts expand only when a node is selected. ## Workflow execution **Runs now follow graph edges only.** A live run advances only when its ephemeral Bot replies, following the graph's edges in order. Nodes start only when their forward predecessors finish and edges reach them. The demo-step timer mechanism has been removed for live runs. The `workflow/demo-step` endpoint remains for replaying canned demos only and refuses while a live run exists. The client polls state while runs are active but does not call `demo-step` for live runs — only Bot replies via `stepResult` move nodes. This is a binding constraint per the owner: workflow execution MUST follow the saved graph structure with edges, gating node completion on ephemeral Bot finish and advancing only along edges. No timer/demo-step advance bypasses the graph. ## Rebased onto main Rebased onto origin/main (commit 5daf756, #1444 merged). No conflicts. #1444's demo UI removal is preserved; no Replay/Run demo buttons or demo-step timers reintroduced. ## Changed files - `plugins/workflow/client.js`: canvas-first Settings, per-node inspector, mini-flowcharts everywhere, modal overflow fix, collapsed drawer by default, Add link form restored - `plugins/workflow/test/client.test.js`: updated for canvas + inspector (select node, then edit via inspector) - `core/src/client/i18n.js`: new strings for inspector UI - `docs/subsystems/workflow.md`: updated invariant 3 and 12 to document graph-only execution - `changelog.d/1438-workflow-ui-unify.added.md`: changelog fragment - `patches/`: regenerated ## Verification Ran at tip `02f2b551b1ec7ffaac8ef215bff8bb1b5e6259e8` (rebased): - ✅ `npm run build` in core/ (passes) - ✅ `npm test` in plugins/workflow/ (58/58 tests pass) - ✅ `node scripts/ds-bot-patches.mjs check` (passes) - ✅ No demo UI strings (Replay/demo-step/Next/Pause) in client.js Not run: - ❌ core unit tests (not relevant to workflow plugin changes) - ❌ lint (requires harness setup) - ❌ smoke test (no index.js/src/host/ changes) Docs-not-needed: core/src/client/i18n.js adds i18n keys for Workflow inspector UI only ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1440, "claim": "Dev", "issue": 1438, "summary": "Settings Workflow graphs are canvas-first with a per-node inspector. Sidebar, Hand-a-task, and drawer show MiniFlowchart previews. Modals keep a sticky Confirm footer. Drawer prompts stay collapsed until a node is selected. Live runs follow graph edges only; product UI has no Replay/Run demo controls after merge with #1444.", "files": ["plugins/workflow/client.js", "plugins/workflow/test/client.test.js", "core/src/client/i18n.js", "docs/subsystems/workflow.md", "changelog.d/1438-workflow-ui-unify.added.md"], "checks": { "ran": "plugins/workflow npm test; ds-bot-patches check; tests-ok", "result": "green", "at": "4f474a0a805edb4fd277cea88028c2d9d9e167be" }, "next": "none — ready for review" } ``` <!-- /flybot:checkpoint --> <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-07569846-0ecd-5c91-ad25-9211e035c190?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-07569846-0ecd-5c91-ad25-9211e035c190&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 5daf756 commit 8f5c9ca

8 files changed

Lines changed: 454 additions & 209 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**Settings → Workflow graphs** is now canvas-first with a per-node inspector panel. Select a node to edit its system prompt, role, and tools — no more wall of textareas. **Workflow stage chat** reuses the normal FlyBot conversation UI (same message bubbles and spacing as Bot/group chats), replacing the previous pipeline-log card style. **Sidebar Workflows list, Hand-a-task modal, and flowchart drawer** now show visual mini-flowcharts instead of text chains like "Planner → Writer → Coder", with a unified visual language across all surfaces. **Hand-a-task modal** overflow fixed: content scrolls, Cancel/Confirm footer is sticky and always visible. **Flowchart drawer** defaults to showing the graph collapsed; system prompts expand only when a node is selected. **Workflow runs** now advance only along graph edges when ephemeral Bots finish — no timer-based demo-step bypass for live runs. The `workflow/demo-step` endpoint remains for replaying canned demos only and refuses while a live run exists.

‎core/client.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ var ZH = {
8787
"Could not open this workflow": "打不开这个工作流",
8888
"This definition cannot be saved": "这个定义不能保存",
8989
"This definition cannot be copied": "这个定义不能复制",
90+
"Select a node to edit": "选择一个节点来编辑",
91+
"Node settings": "节点设置",
92+
Tools: "工具",
93+
"Inputs and outputs": "输入和输出",
9094
"{count} card(s) name a node this workflow draws no column for.": "有 {count} 张卡指向这个工作流不画列的节点。",
9195
// Shared
9296
"Main Bot": "主 Bot",

‎core/src/client/i18n.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ const ZH = {
5353
'Could not open this workflow': '打不开这个工作流',
5454
'This definition cannot be saved': '这个定义不能保存',
5555
'This definition cannot be copied': '这个定义不能复制',
56+
'Select a node to edit': '选择一个节点来编辑',
57+
'Node settings': '节点设置',
58+
Tools: '工具',
59+
'Inputs and outputs': '输入和输出',
5660
'{count} card(s) name a node this workflow draws no column for.': '有 {count} 张卡指向这个工作流不画列的节点。',
5761
// Shared
5862
'Main Bot': '主 Bot',

‎docs/subsystems/workflow.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Everything in `plugins/workflow/`: the graph rules, the run store, the matcher,
3333
| `plugins/workflow/src/match.js` | Which open card matches a Workflow or a local Bot. |
3434
| `plugins/workflow/src/template.js` | 发布交付流水线 (a parallel branch) and the weekly report, each node with the inputs and outputs that edge carries. |
3535
| `plugins/workflow/src/narrate.js` | Progress lines for a step. A live run quotes the Bot reply. The canned delivery copy is the demo player only. A join line is only for a rank of more than one node. |
36-
| `plugins/workflow/client.js` | Sidebar section, chat stage, assign dialog, flowchart editor, and Settings → Workflow graphs. The product UI starts only live runs (assign, ingest, composer); it does not call `workflow/demo-step`. The stage shows the queue and refreshes state while one is active. The stage and the dialogs portal onto `document.body`; a missing container stays in the section tree. |
36+
| `plugins/workflow/client.js` | Sidebar section (with mini-flowcharts), chat stage (normal conversation UI), assign dialog (scrollable with sticky footer), flowchart drawer (collapsed by default, per-node inspector), and Settings → Workflow graphs (canvas-first with inspector panel). The product UI starts only live runs (assign, ingest, composer); it does not call `workflow/demo-step`. The stage shows the queue and refreshes state while one is active. Visual flowcharts replace text chains across all surfaces. The stage and dialogs portal onto `document.body`; a missing container stays in the section tree. |
3737

3838
## Entry points
3939

@@ -46,7 +46,7 @@ Everything in `plugins/workflow/`: the graph rules, the run store, the matcher,
4646

4747
1. Friends' Bots are not nodes. A `remote` Bot is refused by create, define and the matcher.
4848
2. The canvas and the run share one graph: nodes, edges and positions. A drag commits `workflow/graph`. Status highlighting reads that same graph. Replacing edges does not recompute who is already running.
49-
3. A live run advances only when its ephemeral Bot replies, and that reply is the chat line. `workflow/demo-step` exists for unit tests and scripted fixtures only; the browser client does not call it. A run does not create a schedule. `scheduleLabel` is display text. When the host can create Bots, starting a live run (`assign`, `run_workflow`, `ingest`) spawns one ephemeral Bot per node from that node's prompt, role, model and tools, sends it the step from the Main Bot, and removes every instance when the run finishes, fails for good, or is reset. A `failOnce` retry keeps them. They are hidden and left out of the sidebar. Loading the plugin does not spawn Bots for the seeded fixture. Loading is also the one moment a run the host left behind is noticed: a run still marked `running` is abandoned, so loading releases its instances and records the run as `failed`. Nothing resumes it. A run that already ended keeps its own status (#1388). A dispatch that does not land is not marked handed. The chat names the code, and the next hand-off tries that node again. It is not sent twice in the same hand-off. A reply that says `could not answer your message` or `model call failed` fails that node and does not start its successor. A 429 or rate-limit mention in any other reply does not.
49+
3. **A live run advances only when its ephemeral Bot replies, following the graph's edges in order.** That reply is the chat line. Nodes start only when their forward predecessors finish and edges reach them. `workflow/demo-step` exists for unit tests and scripted fixtures only; the browser client does not call it. A run does not create a schedule. `scheduleLabel` is display text. When the host can create Bots, starting a live run (`assign`, `run_workflow`, `ingest`) spawns one ephemeral Bot per node from that node's prompt, role, model and tools, sends it the step from the Main Bot, and removes every instance when the run finishes, fails for good, or is reset. A `failOnce` retry keeps them. They are hidden and left out of the sidebar. Loading the plugin does not spawn Bots for the seeded fixture. Loading is also the one moment a run the host left behind is noticed: a run still marked `running` is abandoned, so loading releases its instances and records the run as `failed`. Nothing resumes it. A run that already ended keeps its own status (#1388). A dispatch that does not land is not marked handed. The chat names the code, and the next hand-off tries that node again. It is not sent twice in the same hand-off. A reply that says `could not answer your message` or `model call failed` fails that node and does not start its successor. A 429 or rate-limit mention in any other reply does not.
5050
4. Each workflow keeps a FIFO queue and up to `maxConcurrent` live runs (default 2, an integer from 1 to 8 on the record or via `workflow/concurrency`). The host runs at most 6 live runs at once. A task that does not fit is enqueued. When a run finishes, every workflow with a free slot is drained, oldest enqueue first, until the host cap. A new assign on a workflow that already has a queue waits behind it. A task does not replace a running run or release that run's Bots. An old store run is a demo unless it is still `running` and has ephemeral Bot ids. History records a finished or failed run only. Lowering the cap does not stop a run that has already started. Assigning `{ botId }` claims the card for that local Bot and does not enqueue. A remote Bot is refused.
5151
5. A node declares up to eight inputs and eight outputs. A required input is an output of the same name on an ancestor, or `task`, `title`, or `brief` on a root. A start with no provider is refused, and Bots spawned for that attempt are released. On a Bot-backed run a successor stays queued until its required inputs are present. If every forward predecessor is done, failed or skipped and an input is still missing, that node fails and the run stops. The dispatch text carries `Input <name>: <value>`. The Bot reports `OUTPUT <name>: <value>`; a single declared output may be the reply body. Nodes start in edge order.
5252
6. Each node is a real ephemeral Bot for that run, then it is removed. A permanent sidebar Bot (`botId`) is optional and is not required for the step to run. `tools` on the node is what that Bot may use: `github` grants `mcp__github__*` (pull requests, reviews, comments); `bash` or `shell` sets the permission to `danger-full-access` and allows a full-access shell; any other step gets `workspace-write`. A hidden run Bot cannot show an approval card, so a granted tool is allowed and a connector it did not name is refused. The host stores this on the run Bot as `stepTools` and `permission`.
@@ -55,7 +55,7 @@ Everything in `plugins/workflow/`: the graph rules, the run store, the matcher,
5555
9. The browser draws text only. Names and messages are React text children. The unit renderer asserts a hostile name is not markup.
5656
10. `enabled: false` registers no endpoint, tool or listener and writes nothing.
5757
11. A sidebar click opens the stage or a dialog and leaves the Workflows section in place. The stage and the dialogs portal onto `document.body`. When that container is missing they stay in the section tree; the click does not throw.
58-
12. A node's prompt and the graph are one record. Settings → Workflow graphs, the flowchart's prompt fields, and `define_workflow` all write `workflow/graph`. A run reads that record; it does not define it. After a live run finishes, the stage shows `lane.last` for that workflow until a new live run starts. Seeded fixture scripts stay in `state.demos` for tests; the product UI does not step them.
58+
12. A node's prompt and the graph are one record. Settings → Workflow graphs (canvas-first with per-node inspector), the flowchart drawer (collapsed by default, inspector on select), and `define_workflow` all write `workflow/graph`. A run reads that record; it does not define it. After a live run finishes, the stage shows `lane.last` for that workflow until a new live run starts. Seeded fixture scripts stay in `state.demos` for tests; the product UI does not step them.
5959

6060
## Tests
6161

‎patches/ds-bot/0001-core-fixes.patch‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ diff --git a/src/client/feedback.js b/src/client/feedback.js
578578
diff --git a/src/client/i18n.js b/src/client/i18n.js
579579
--- a/src/client/i18n.js
580580
+++ b/src/client/i18n.js
581-
@@ -5,6 +5,55 @@
581+
@@ -5,6 +5,59 @@
582582
export const NAMESPACE = 'ds-bot'
583583

584584
const ZH = {
@@ -630,6 +630,10 @@ diff --git a/src/client/i18n.js b/src/client/i18n.js
630630
+ 'Could not open this workflow': '打不开这个工作流',
631631
+ 'This definition cannot be saved': '这个定义不能保存',
632632
+ 'This definition cannot be copied': '这个定义不能复制',
633+
+ 'Select a node to edit': '选择一个节点来编辑',
634+
+ 'Node settings': '节点设置',
635+
+ Tools: '工具',
636+
+ 'Inputs and outputs': '输入和输出',
633637
+ '{count} card(s) name a node this workflow draws no column for.': '有 {count} 张卡指向这个工作流不画列的节点。',
634638
// Shared
635639
'Main Bot': '主 Bot',

‎patches/ds-bot/0008-client-bundle.patch‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ FlyBot patch 0008-client-bundle on Fei2411/DeepSeek-Bot@2b10c70 (ds-bot/). Gener
33
diff --git a/client.js b/client.js
44
--- a/client.js
55
+++ b/client.js
6-
@@ -42,6 +42,52 @@ module.exports = __toCommonJS(index_exports);
6+
@@ -42,6 +42,56 @@ module.exports = __toCommonJS(index_exports);
77
// src/client/i18n.js
88
var NAMESPACE = "ds-bot";
99
var ZH = {
@@ -52,6 +52,10 @@ diff --git a/client.js b/client.js
5252
+ "Could not open this workflow": "打不开这个工作流",
5353
+ "This definition cannot be saved": "这个定义不能保存",
5454
+ "This definition cannot be copied": "这个定义不能复制",
55+
+ "Select a node to edit": "选择一个节点来编辑",
56+
+ "Node settings": "节点设置",
57+
+ Tools: "工具",
58+
+ "Inputs and outputs": "输入和输出",
5559
+ "{count} card(s) name a node this workflow draws no column for.": "有 {count} 张卡指向这个工作流不画列的节点。",
5660
// Shared
5761
"Main Bot": "主 Bot",

0 commit comments

Comments
 (0)