Skip to content

[local-explorer-ui] Add Workflows diagram#13334

Open
pombosilva wants to merge 1 commit intomainfrom
osilva/add-local-workflows-diagram
Open

[local-explorer-ui] Add Workflows diagram#13334
pombosilva wants to merge 1 commit intomainfrom
osilva/add-local-workflows-diagram

Conversation

@pombosilva
Copy link
Copy Markdown
Contributor

@pombosilva pombosilva commented Apr 7, 2026

Fixes WOR-1199.

Adds the diagram of workflow steps to the local explorer UI ( to match production Workflows dashboard). The diagram is generated by static analysis of the workflow source code. For this, we vendor a WASM build of the Rust-based visualizer-controller (the same parser that powers the production diagram). Vendoring was chosen because the parser is not yet ready to be open-sourced as a standalone npm package, but we still wanted exact production parity rather than maintaining a separate JS parser. The WASM binary is ~982KB.

Changes

Wrangler:

  • vendor/workflow-dag-parser/: vendored WASM build of the visualizer-controller (JS wrapper + .wasm binary)
  • src/workflows/dag-parser.ts: calls the vendored parser on the esbuild bundle output and maps results per workflow
  • src/workflows/dag-types.ts: TS types matching the parser's output format
  • src/dev/miniflare/index.ts: parses dags once per bundle change, threads them through workflow options
  • tsup.config.ts: esbuild plugin to copy .wasm to wrangler-dist/

Miniflare:

  • plugins/shared/index.ts: WorkflowDagPayload type and dag field on WorkflowOption
  • plugins/workflows/index.ts: Zod schema accepts dag
  • plugins/core/types.ts: dag field on WorkflowBindingInfo
  • plugins/core/explorer.ts: passes dag through to explorer binding map
  • src/index.ts: threads dag through workflow options collection
  • workers/local-explorer/resources/workflows.ts: getWorkflowDag handler
  • workers/local-explorer/explorer.worker.ts: GET /api/workflows/:name/graph route
  • workers/local-explorer/openapi.local.json: new endpoint + schema

Local Explorer UI:

  • components/workflows/diagram/: full diagram rendering, ported from the production Workflows dashboard (WorkflowDiagram, DAGWrapper, connectors, step cards, icons, BackgroundDots, CopyDiagramButton)
  • routes/workflows/$workflowName/index.tsx: side-by-side layout with instances table + diagram panel, expand/collapse toggle, copy/download/refresh buttons
image
  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because: WIP
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: WIP

A picture of a cute animal (not mandatory, but encouraged)


Open with Devin

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 7, 2026

🦋 Changeset detected

Latest commit: cff1feb

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk bot commented Apr 7, 2026

Each call to hasSteps(node, functions) at line 280 creates a fresh new Set() since no third arg is passed — the default parameter creates a fresh set each time. This is correct since each node's check starts fresh at the top-level call, and only shares the visited set within its own recursive subtree to prevent cycles there.

Now let me verify the getWorkflowDag handler doesn't have peer aggregation support (unlike the other workflow handlers):

Looking at the getWorkflowDag function in workflows.ts:340-363, I notice it does NOT attempt to proxy to peer instances for aggregation, unlike getWorkflowDetails, listWorkflowInstances, etc. This is potentially an issue since cross-instance workflows won't have their DAGs accessible.

However, considering that DAGs are derived from static analysis of the source code at bundle time, and only the wrangler instance that owns the workflow would have the bundled source, this seems intentional. The DAG data is embedded in the binding map at bundling time, so only the owner would have it.

Let me now confirm there are no issues with the FunctionCall type having an optional nodes property in the UI types but not in the wrangler types:

The UI FunctionCall type (in types.ts:99-105) has nodes?: Node[] while the wrangler dag-types.ts:114-119 FunctionCall does NOT have nodes. However, this is not a runtime issue since:

  1. The wrangler types define what the parser produces
  2. The UI types define what the UI consumes
  3. The data flows from parser -> wrangler -> miniflare -> explorer worker -> UI, and nodes on FunctionCall is optional in the UI types, so if the parser doesn't produce it, the UI handles it gracefully

After thorough review, this PR looks well-structured. The architecture is clean - data flows correctly from WASM parser through wrangler to miniflare to the explorer worker to the UI. Let me check one last thing about the entrypointSource usage pattern to make sure the DAG parsing doesn't happen too frequently:

The DAG parsing happens inside buildMiniflareBindingOptions which is called on bundle changes. The IIFE at line 768 ensures parseWorkflowDags is called once per build, not once per workflow. This is efficient.

LGTM

github run

@pombosilva pombosilva force-pushed the osilva/add-local-workflows-diagram branch 5 times, most recently from d88648d to 5d6cffb Compare April 8, 2026 08:55
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 8, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@13334

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@13334

miniflare

npm i https://pkg.pr.new/miniflare@13334

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@13334

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@13334

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@13334

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@13334

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@13334

wrangler

npm i https://pkg.pr.new/wrangler@13334

commit: cff1feb

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

✅ All changesets look good

Review Summary:

  1. local-explorer-ui-workflow-diagram.md - @cloudflare/local-explorer-ui: minor

    • Well-written description of the new workflow diagram feature
    • No markdown headers
  2. miniflare-workflow-dag-api.md - miniflare: minor

    • Clear explanation of the API endpoint and plumbing
    • No markdown headers
  3. wrangler-workflow-dag-parser.md - wrangler: minor

    • Good description of the WASM parser and lazy loading
    • No markdown headers

All version types are appropriate (minor for new features), descriptions are meaningful, and there are no formatting issues.

@pombosilva pombosilva force-pushed the osilva/add-local-workflows-diagram branch 3 times, most recently from abcf6f6 to 2d59c0a Compare April 9, 2026 13:03
@pombosilva pombosilva marked this pull request as ready for review April 9, 2026 13:03
@workers-devprod workers-devprod requested review from a team and dario-piotrowicz and removed request for a team April 9, 2026 13:04
@workers-devprod
Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/workflows
  • @cloudflare/wrangler
Show detailed file reviewers
  • packages/local-explorer-ui/package.json: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/e2e/utils.ts: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/e2e/workflows/workflow.spec.ts: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/StatusBadge.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/StepRow.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/Timestamp.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/BackgroundDots.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/CopyDiagramButton.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/DAGWrapper.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/WorkflowDiagram.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/connectors.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/context.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/icons.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/index.ts: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/step.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/transitions.ts: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/components/workflows/diagram/types.ts: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/routes/workflows/$workflowName/$instanceId.tsx: [@cloudflare/wrangler]
  • packages/local-explorer-ui/src/routes/workflows/$workflowName/index.tsx: [@cloudflare/wrangler]
  • packages/miniflare/src/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/core/explorer.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/core/types.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/shared/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/workflows/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/local-explorer/explorer.worker.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/local-explorer/openapi.local.json: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/local-explorer/resources/workflows.ts: [@cloudflare/wrangler]
  • packages/miniflare/test/plugins/local-explorer/workflows.spec.ts: [@cloudflare/wrangler]
  • packages/workflows-shared/src/context.ts: [@cloudflare/workflows @cloudflare/wrangler]
  • packages/wrangler/src/dev/miniflare/index.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/workflows/dag-parser.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/workflows/dag-types.ts: [@cloudflare/wrangler]
  • packages/wrangler/tsup.config.ts: [@cloudflare/wrangler]
  • packages/wrangler/vendor/workflow-dag-parser/index.d.ts: [@cloudflare/wrangler]
  • packages/wrangler/vendor/workflow-dag-parser/index.js: [@cloudflare/wrangler]
  • packages/wrangler/vendor/workflow-dag-parser/visualizer_controller_bg.wasm: [@cloudflare/wrangler]
  • pnpm-lock.yaml: [@cloudflare/wrangler]

@pombosilva pombosilva force-pushed the osilva/add-local-workflows-diagram branch from 2d59c0a to 1663d07 Compare April 9, 2026 13:06
devin-ai-integration[bot]

This comment was marked as resolved.

@pombosilva pombosilva force-pushed the osilva/add-local-workflows-diagram branch from 1663d07 to 3f2bef8 Compare April 9, 2026 13:45
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 8 additional findings in Devin Review.

Open in Devin Review

@pombosilva pombosilva force-pushed the osilva/add-local-workflows-diagram branch from 3f2bef8 to cff1feb Compare April 9, 2026 13:57
@dario-piotrowicz dario-piotrowicz requested review from NuroDev and removed request for dario-piotrowicz April 10, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

2 participants