Skip to content

feat(workflows): IDE-style reference viewer for workflows#5854

Merged
waleedlatif1 merged 6 commits into
stagingfrom
feat/workflow-references-clean
Jul 22, 2026
Merged

feat(workflows): IDE-style reference viewer for workflows#5854
waleedlatif1 merged 6 commits into
stagingfrom
feat/workflow-references-clean

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Supersedes #5852 — builds directly on @mzxchandra's branch (both original commits preserved) and layers a cleanup/alignment pass on top. Huge thanks to Chandra for the feature itself: the recursive caller/callee resolver, the cycle/diamond handling, and the modal UI all originate there.

What the feature does

Right-click a workflow in the sidebar → Show references opens a modal with two tabs: Used by (workflows that call it) and Uses (workflows it calls), each a recursive tree whose rows navigate to the referenced workflow. Resolution reads live editor state (draft workflow_blocks), resolves the ACTIVE canonical mode so a dormant basic/advanced value can't mask the live one, marks cycles as leaves, and bounds diamond re-expansion.

Changes on top of #5852

Coverage

  • Added the third call-edge shape: workflow_input tools inside tool-input sub-blocks (an agent invoking another workflow as a tool) now appear in both trees, with array and JSON-stringified values handled via the shared coerceObjectArray helper. Non-call selector shapes (workflowSelector, trigger workflowIds) are deliberately excluded and documented against remapWorkflowReferencesInSubBlocks.

Auth

  • The route now authorizes like its /api/workflows/[id]/* siblings via authorizeWorkflowByWorkspacePermission and derives the workspace server-side — proper 404/403 semantics, and the client-supplied workspaceId query param is gone from the contract, hook, and modal.

UX

  • Restored native cmd/ctrl+click open-in-new-tab on sidebar workflow rows; references stay one right-click away in the context menu.
  • ReferencesModal mounts on demand per row instead of always-mounted-per-row — removes N idle React Query observers in large workspaces and deletes the prevIsOpen reset machinery, the enabled knob, and the staleTime: 0 workaround (now a named 30s constant).

Design system

  • Tree rows land on the modal's px-4 text gutter, use --text-icon / --surface-hover tokens and the emcn Workflow icon instead of a hardcoded brand hex.

Hardening / hygiene

  • Escaped LIKE wildcards in the custom_block_ prefix match; imported MAX_CALL_CHAIN_DEPTH instead of mirroring it; un-exported the internal graph builder; removed dead fallbacks, a duplicate not-found scan, and a redundant row-narrowing map.
  • Route tests updated for the authz shape (401/404/403/200); resolver tests extended for tool-input edges (18 tests passing).

Verification

  • bunx vitest run on both test files: 18/18 passing
  • bun run check:api-validation and :strict: pass (baseline 966→967 for the new route)
  • biome check clean; tsc clean on all touched files

mzxchandra and others added 4 commits July 22, 2026 11:08
Adds a "Show references" viewer so you can see how workflows connect:
which workflows call a given workflow ("Used by") and which workflows it
calls ("Uses"), rendered as recursive, clickable trees.

- Opened via Cmd/Ctrl+click on a sidebar workflow row and a "Show
  references" context-menu item.
- Resolves references through both the workflow / workflow_input blocks
  (reusing isWorkflowBlockType) and published custom blocks
  (custom_block_* -> source workflow), scoped to the workspace.
- Builds the whole workspace reference graph once from live workflow_blocks
  state; cycle-safe DFS marks A->B->A loops as (cycle) leaves.
- Contract-bound GET /api/workflows/[id]/references with workspace-level
  authz; React Query hook gated to fetch only when the modal opens.
- Unit tests for the pure graph/tree logic (cycles, self-refs, dangling
  drop, custom-block + workflow_input resolution) and route tests
  (401/400/403/200).
… cache, and graph size

Addresses review findings on the reference viewer:

- Resolve the workflow-block child via resolveActiveCanonicalValue (the
  shared SOT) instead of basic-first `||`, so an advanced-mode block whose
  old basic workflowId value lingers resolves to the active manual value.
- Keep self-references (A -> A) and render them as a cycle leaf instead of
  dropping the edge, matching the cycle-safe viewer's purpose.
- Set the references query staleTime to 0 so reopening the always-mounted
  modal refetches live editor state instead of serving a stale cached graph.
- Bound converging paths: a node already expanded elsewhere in the tree is
  emitted once more as a plain leaf (edge stays visible) rather than
  re-expanded, so a densely reconverging graph can't grow exponentially.
… with platform conventions

- authorize via authorizeWorkflowByWorkspacePermission and derive the
  workspace server-side (404/403 semantics; drops the client-supplied
  workspaceId query param from the contract, hook, and modal)
- add workflow-tool call edges: workflow_input tools inside tool-input
  sub-blocks now appear in both trees; non-call selector shapes stay
  deliberately excluded (documented against remap-internal-ids)
- restore native cmd/ctrl+click open-in-new-tab on sidebar workflow rows;
  references stay reachable from the context menu
- mount ReferencesModal on demand per row, deleting the prevIsOpen reset,
  the enabled knob, and the staleTime-0 workaround (now 30s)
- align the tree with design tokens (--text-icon, --surface-hover, px-4
  text gutter) and drop the hardcoded brand hex
- escape LIKE wildcards in the custom_block_ prefix match; import
  MAX_CALL_CHAIN_DEPTH instead of mirroring it; remove dead fallbacks,
  the duplicate not-found scan, and the redundant custom-block row map
- drop the vestigial isOpen prop (conditional mount owns visibility)
- unify on the emcn Workflow icon in tree rows
- inline the static className and derive nodes without an annotation
- remove one restating test comment
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 22, 2026 8:34pm

Request Review

@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New read API exposes workspace call graphs from draft block data; auth follows existing workflow read checks, but resolver complexity and SQL over subBlocks/tool-input JSON warrant careful review.

Overview
Adds an IDE-style workflow references flow: sidebar context menu Show references opens a modal with Used by and Uses tabs, each a recursive tree; rows navigate to the target workflow. The modal loads via useWorkflowReferences and mounts on demand per row.

Introduces GET /api/workflows/[id]/references with session checks and authorizeWorkflowByWorkspacePermission (read); workspace is derived server-side and getWorkflowReferences returns scoped callers / callees trees. Shared Zod contract (ReferenceNode, recursive schema) wires the route and client.

New resolveWorkflowReferences / getWorkflowReferences build call edges from draft workflow_blocks: workflow / workflow_input blocks (active basic vs advanced workflowId), custom blocks, and agent tool-input workflow tools (including JSON-stringified values and per-tool canonical modes). Trees mark cycles, collapse diamond re-expansion, and cap depth at MAX_CALL_CHAIN_DEPTH. Route and resolver tests cover auth and edge cases; API validation baseline bumps 966→967.

Reviewed by Cursor Bugbot for commit 809971b. Configure here.

Comment thread apps/sim/lib/workflows/references/operations.ts
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an IDE-style reference viewer for workflows. The main changes are:

  • Adds an authenticated API for workspace-scoped workflow references.
  • Resolves recursive caller and callee trees from live workflow blocks.
  • Supports direct, custom-block, and tool-input workflow calls.
  • Adds an on-demand sidebar modal with reference navigation.
  • Refetches cached reference data whenever the modal reopens.

Confidence Score: 5/5

This looks safe to merge.

  • The reference query now becomes stale immediately and refetches whenever the modal reopens.
  • The API applies the established workflow authorization path and server-side workspace scope.
  • No blocking issues remain in the changed code.

Important Files Changed

Filename Overview
apps/sim/hooks/queries/workflow-references.ts Adds the reference query with workflow-specific cache keys and refetch-on-reopen behavior.
apps/sim/app/api/workflows/[id]/references/route.ts Adds contract validation, session checks, workflow authorization, and server-derived workspace scoping.
apps/sim/lib/workflows/references/operations.ts Builds recursive reference trees with active-mode resolution, cycle handling, and bounded expansion.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/references-modal/references-modal.tsx Adds the on-demand modal with caller and callee tabs, loading states, and workflow navigation.

Reviews (3): Last reviewed commit: "fix(workflows): cover legacy workflow-ty..." | Re-trigger Greptile

Comment thread apps/sim/hooks/queries/workflow-references.ts Outdated
…keep the reference cache live

- workflow_input tools inside tool-input now resolve basic/advanced via the
  index-scoped canonicalModes override, mirroring execution (Cursor finding)
- staleTime back to 0: no mutation invalidates this key, so a reopen must
  background-refetch; on-demand mounting keeps the cached tree painting
  instantly (Greptile P1)
- modal header uses the em-dash label-entity convention; tree items carry
  aria-level instead of a static aria-selected
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/workflows/references/operations.ts
…ncated expansions

- toolInputCallees matches both workflow tool type spellings via
  isWorkflowBlockType and passes the tool's own type as the legacy
  canonicalModes fallback, matching providers/utils resolution
- a depth-capped expansion no longer poisons the expanded set, so a
  shallower path re-expands the node in full (Cursor finding)
- the allowed-but-workspaceless auth branch now returns 403, not the
  authz result's 200
- tests: legacy tool type + per-tool index-scope isolation, diamond
  re-expansion with a real subtree, depth ceiling, shallow-path retry
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 809971b. Configure here.

@waleedlatif1
waleedlatif1 merged commit 6f33a94 into staging Jul 22, 2026
20 checks passed
@waleedlatif1
waleedlatif1 deleted the feat/workflow-references-clean branch July 22, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants