Skip to content

Genie 758/story/allow to edit blueprint#102

Open
MayaCrmi wants to merge 7 commits intomainfrom
GENIE-758/story/allow-to-edit-blueprint
Open

Genie 758/story/allow to edit blueprint#102
MayaCrmi wants to merge 7 commits intomainfrom
GENIE-758/story/allow-to-edit-blueprint

Conversation

@MayaCrmi
Copy link
Collaborator

@MayaCrmi MayaCrmi commented Feb 25, 2026

Summary

This PR adds the ability to edit an existing blueprint from the Agentic Workflows page. Clicking the new edit (pencil) button on a workflow loads it back into the graph canvas, where the user can modify it and save the updated version.

Important Changes

New file: use-load-blueprint.ts

  • Reconstructs the full React Flow graph from a blueprint's spec_dict fetched via getBlueprintInfo.
  • Uses logic similar to the old display graph logic for hierarchical layout matching the display graph's constants.

use-graph-logic.ts

  • Accepts an optional editBlueprintId to enter edit mode instead of starting with an empty canvas.
  • After building blocks finish loading, calls loadBlueprintForEditing to fit the UI to the current graph.
  • Save logic calls new PUT /blueprints/blueprint.update when in edit mode, updating the blueprint in-place and preserving its original ID.
  • Extracted YamlFlowState and related interfaces into use-load-blueprint.ts to avoid duplication.

WorkflowsPanel.tsx / AgentFlowGraph.tsx

  • New onFlowEdit callback and showEditButton prop thread the edit action from the pencil icon up to the page.
  • Pencil button renders next to each workflow in the sidebar with stopPropagation so it doesn't trigger flow selection.

GraphHeader.tsx

  • Button label toggles between "Save Workflow" and "Update Workflow" based on isEditMode.

SaveBlueprintModal.tsx

  • Pre-fills name/description fields when in edit mode via currentName / currentDescription props.
  • All labels, placeholders, and loading states adapt between "Save" and "Update" wording.

Delete Node Changes Clarification

The changes in the deleteNode logic are needed to fix a bug that was already there before this new feature. The edit flow exposed the issue because loading a saved blueprint creates a fully connected graph, with after as arrays and multiple branch targets. Deleting a middle node in that structure left dangling references in the YAML.
The fix makes deleteNode consistent with the cleanup logic already used in deleteEdge: it removes the deleted node’s ID from after arrays (collapsing to a string or removing when empty), deletes branch entries that target the node (and clears exit_condition if no branches remain), uses updatedNodes instead of prevFlow.nodes so the YAML actually updates, and spreads ...prevFlow in all setYamlFlow calls so name and description aren’t accidentally dropped.

Addressing Concerns About YAML & Graph Integrity

This edit flow is built as a clean, lossless round-trip. When a blueprint is opened for editing, we load the original spec_dict from the backend and copy its nodes, plan, and conditions directly into yamlFlow. That same yamlFlow object is what we use when generating YAML on save. The React Flow graph is just a visual layer using that data - it doesn’t recreate or reinterpret the blueprint. So all $ref pointers, after/branch connections, exit_condition mappings, and node configs stay exactly as they were.
Edits made in the UI (adding nodes, connecting edges, attaching conditions) go through the same setYamlFlow logic used when building a new graph. There’s no separate “edit mode” mutation path.
The only real difference is what happens at save time - in edit mode, we call PUT /blueprints/blueprint.update, which updates the existing document in place - keeping the same ID, metadata, and sharing settings. This is unlike the new-build mode, where we call POST /blueprints/blueprint.save.

Summary by CodeRabbit

  • New Features

    • Workflow editing: edit button in workflows list; graph builder can load and modify existing workflows with preserved name/description.
    • In-place update: save flow now supports updating an existing workflow (UI shows "Update Workflow"/"Updating..." in edit mode).
    • Blueprint editing API: added support for updating blueprints in-place and client-side call to trigger it.
    • Improved graph reconstruction/layout when loading existing workflows.
  • Bug Fixes

    • Robust loading: edit-load failures show clear feedback and fall back to a blank canvas.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Adds blueprint edit/save flow: backend PUT endpoint and service error translation; client API for update; large frontend changes to load, reconstruct, render, and update blueprints (edit-mode state, UI edit buttons, graph reconstruction hook, and wiring through pages/hooks/components).

Changes

Cohort / File(s) Summary
Backend API & Service
multi-agent/api/flask/endpoints/blueprints.py, multi-agent/blueprints/service.py
New PUT handler /blueprint.update and update_draft() now translates missing-repo KeyError into BlueprintNotFoundError, with added error handling and logging.
Frontend API Client
ui/client/src/api/blueprints.ts
Added updateBlueprint(blueprintId, blueprintRaw) to call PUT /blueprints/blueprint.update and return save response.
Graph reconstruction & loader
ui/client/src/hooks/use-load-blueprint.ts
New module exposing reconstructBlueprintGraph() and loadBlueprintForEditing(); builds React Flow nodes/edges and a YamlFlowState from spec_dict, computes layout, resolves blocks/conditions, and exports related types.
Graph logic & editing hook
ui/client/src/hooks/use-graph-logic.ts
Added editBlueprintId option and edit-mode lifecycle: load existing blueprint, populate nodes/edges/yamlFlow, switch save path to updateBlueprint, expose isEditMode/editBlueprintName/editBlueprintDescription, and adjust deletion/edge logic for edits.
Workspace / Page wiring
ui/client/src/workspace/NewGraph.tsx, ui/client/src/pages/AgenticWorkflows.tsx
Added editBlueprintId prop/state; handleOpenGraphBuilder(flow?) to open builder for editing; pass editBlueprintId into NewGraph to pre-load editing session.
Graph UI components
ui/client/src/components/agentic-ai/AgentFlowGraph.tsx, ui/client/src/components/agentic-ai/WorkflowsPanel.tsx, ui/client/src/components/agentic-ai/graphs/GraphCanvas.tsx, ui/client/src/components/agentic-ai/graphs/GraphHeader.tsx, ui/client/src/components/agentic-ai/graphs/SaveBlueprintModal.tsx
Added onFlowEdit callback and showEditButton in WorkflowsPanel; propagate onFlowEdit and isEditMode through AgentFlowGraphGraphCanvasGraphHeader; SaveBlueprintModal supports edit-mode props and adapts UI/behavior for updates.
Small changes
ui/client/src/components/agentic-ai/WorkflowsPanel.tsx (icons/tooltip wiring)
Added Pencil icon and edit-button rendering per item when showEditButton is true.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant UI as AgenticWorkflows
    participant Builder as NewGraph
    participant Hook as useGraphLogic
    participant Loader as useLoadBlueprint
    participant API as ClientAPI
    participant Server as Backend

    User->>UI: Click edit on workflow
    UI->>UI: set editingBlueprintId
    UI->>Builder: open with editBlueprintId
    Builder->>Hook: init with editBlueprintId
    Hook->>Loader: loadBlueprintForEditing(blueprintId)
    Loader->>API: getBlueprintInfo(blueprintId)
    API->>Server: GET /blueprints/info/{id}
    Server-->>API: spec_dict
    API-->>Loader: spec_dict
    Loader->>Loader: reconstructBlueprintGraph(spec_dict)
    Loader-->>Hook: ReconstructedGraph (nodes, edges, yamlFlow)
    Hook->>Builder: populate editor state (isEditMode=true)
    User->>Builder: modify graph
    User->>Builder: click "Update Workflow"
    Builder->>Hook: onSave (blueprintRaw)
    Hook->>API: updateBlueprint(blueprintId, blueprintRaw)
    API->>Server: PUT /blueprints/blueprint.update
    Server-->>API: 200 OK / error
    API-->>Hook: response
    Hook->>Builder: onSaveComplete / show feedback
    Builder->>UI: navigate back / clear editing state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • odaiodeh
  • sfiresht
  • yhabushi79

Poem

🐰
I hopped in to mend a blueprint bright,
Unfurled the nodes by soft moonlight,
I patched the branches with carrot glue,
Pressed update — now the workflow’s new! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Genie 758/story/allow to edit blueprint' is partially related to the main changeset. It references a real aspect of the change (adding blueprint editing capability), but includes a branch/issue identifier format that doesn't clearly summarize the feature for developers scanning history.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch GENIE-758/story/allow-to-edit-blueprint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@MayaCrmi MayaCrmi closed this Feb 25, 2026
@MayaCrmi MayaCrmi reopened this Feb 25, 2026
@github-actions
Copy link

Here is the code review for the UnifAI Edit Workflow Pull Request.

🔍 Summary

This PR implements the "Edit Workflow" functionality, allowing users to load existing blueprints into the NewGraph builder, modify them, and update them in place.

  • Backend: Added PUT endpoint for blueprint updates.
  • UI: Added use-load-blueprint hook to reconstruct ReactFlow graphs from saved YAML plans, integrated dagre for auto-layout on load, and updated the graph builder state machine to handle edit mode.

Overall, the separation of the reconstruction logic into a new hook is a strong architectural choice, preventing further bloating of the use-graph-logic hook.

🧩 File-by-file feedback

[DOMAIN: BACKEND] multi-agent/api/flask/endpoints/blueprints.py

  • Logic: The update_blueprint endpoint correctly uses @from_body to map frontend camelCase keys to backend snake_case arguments. Error handling covers standard cases (404, 400).

[DOMAIN: BACKEND] multi-agent/blueprints/service.py

  • Improvement: Explicitly catching KeyError and raising BlueprintNotFoundError aligns with the service layer pattern.

[DOMAIN: UI] ui/client/src/hooks/use-load-blueprint.ts

  • ⚠️ Missing Dependency: This file imports @dagrejs/dagre. This package is not listed in the provided package.json context or Architecture Tech Stack.
    • Action: Ensure @dagrejs/dagre and its types (@types/dagre) are added to package.json and pnpm-lock.yaml. Relying on transitive dependencies from ReactFlow is unsafe.
  • Refactoring: Extracting reconstructBlueprintGraph here is excellent. It adheres to the convention of keeping complex logic out of components.

[DOMAIN: UI] ui/client/src/hooks/use-graph-logic.ts

  • State Management: The useEffect loading pattern using blueprintLoadedRef correctly handles React Strict Mode double-invocation.
  • Error Handling: The fallback to an empty canvas with a toast notification upon load failure is a good user experience pattern (use-toast.ts usage is correct).

[DOMAIN: UI] ui/client/src/components/agentic-ai/graphs/SaveBlueprintModal.tsx

  • Convention: The component correctly uses the custom Tailwind utility class input-dark-theme per ui/ARCHITECTURE.md.
  • State Sync: The useEffect syncing props to state (currentName) is acceptable here, but ensure the modal's onClose fully resets the parent's state to prevent stale data if the modal is reopened for a "Save As" action later (though "Save As" isn't implemented yet, it's good practice).

[DOMAIN: UI] ui/client/src/pages/AgenticWorkflows.tsx

  • UX Issue: In handleBackToFlowConfig, if a user cancels editing (goes back without saving), setSelectedFlow(null) is called.
    • Feedback: This deselects the workflow they were just looking at. It would be better UX to re-select the flow defined by editingBlueprintId so they return to the "View Mode" of that specific workflow.

[DOMAIN: UI] ui/client/src/workspace/NewGraph.tsx

  • Performance: The loading state is handled inside useGraphLogic, but NewGraph renders GraphCanvas immediately.
    • Observation: If dagre layout takes time or the fetch is slow, the user might see a flash of the default "User Input -> Final Answer" nodes before the loaded graph snaps into place. Consider passing an isLoading prop to GraphCanvas to show a spinner overlay during the initial edit-load phase.

🛠 Suggested Improvements

1. Preserve Selection on Cancel (UI)
In ui/client/src/pages/AgenticWorkflows.tsx, modify the back handler to keep the current flow selected if the user cancels:

// ui/client/src/pages/AgenticWorkflows.tsx

const handleBackToFlowConfig = useCallback((savedBlueprint?: SavedBlueprintInfo) => {
  // Store the ID before clearing state
  const wasEditingId = editingBlueprintId; 
  
  setShowGraphBuilder(false);
  setEditingBlueprintId(null);
  
  if (savedBlueprint?.blueprintId) {
    // ... existing logic for saved flow ...
  } else if (wasEditingId) {
    // 🛠️ UX Fix: If cancelling edit, keep the original flow selected
    // Note: You might need to ensure 'projects' or flow list is available to find the full object, 
    // or just rely on the ID if WorkflowsPanel handles id-based selection.
    // If not, leaving it null is safer than passing a partial object, but inconsistent.
  } else {
    setSelectedFlow(null);
  }
}, [editingBlueprintId]);

2. Type Safety for Workspace Data
In use-load-blueprint.ts, the workspaceData construction uses hardcoded strings. It is safer to use the BuildingBlock interface from @/types/graph.

import { BuildingBlock } from "@/types/graph";
// ...
workspaceData: {
  // ...
  category: "nodes", // ⚠️ Consider using a constant or enum if available
  // ...
} as BuildingBlock['workspaceData']

✅ What's Good

  • Strict Separation: The distinction between "Edit Mode" (ReactFlow) and "View Mode" (JointJS) described in the Architecture doc is respected. The PR correctly uses ReactFlow for the editing capability.
  • Refactoring: Moving the types (YamlFlowNode, YamlFlowState) to use-load-blueprint.ts and importing them elsewhere cleans up use-graph-logic.ts significantly.
  • API Pattern: The updateBlueprint function in api/blueprints.ts follows the project's strict API module separation and naming conventions.

✍️ Suggested Commit Message

feat(ui): add workflow edit capability

- Add PUT /blueprint.update endpoint to backend
- Implement `use-load-blueprint` hook with Dagre layout for graph reconstruction
- Add edit mode support to NewGraph and useGraphLogic
- Update AgenticWorkflows page to support opening workflows in builder

@@ -278,15 +258,48 @@ export const useGraphLogic = (options: UseGraphLogicOptions = {}) => {
const updatedPlan = prevFlow.plan
.filter((step) => step.uid !== nodeId)
.map((step) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Please read explanation for this in the description. To see the bug this is fixing try and build a graph say with an Orchestrator connected bidirectionally to two nodes and then delete one of those nodes and you'll see you don't get validation even though you should've, since the deletion doesn't remove the node properly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@multi-agent/blueprints/service.py`:
- Around line 52-53: The current except block re-raises BlueprintNotFoundError
from a caught KeyError without explicit chaining; change the handler to "except
KeyError as err:" and re-raise with explicit suppression of the original context
to avoid leaking repository internals by using "raise
BlueprintNotFoundError(blueprint_id) from None" (update the except block around
BlueprintNotFoundError/KeyError in service.py).

In `@ui/client/src/hooks/use-graph-logic.ts`:
- Around line 640-642: Replace the one-shot boolean guard
blueprintLoadedRef.current with a ref that tracks the last loaded blueprint ID:
change blueprintLoadedRef to something like lastLoadedBlueprintIdRef and update
the guard in the useGraphLogic hook to return early when
lastLoadedBlueprintIdRef.current === editBlueprintId (also include checks for
!editBlueprintId and isLoadingBlocks), then set lastLoadedBlueprintIdRef.current
= editBlueprintId after loading; apply the same ID-based guard changes to the
other block-loading logic around the 668-680 region so new editBlueprintId
values trigger reloads and avoid saving stale canvas data with the wrong
editBlueprintId.

In `@ui/client/src/hooks/use-load-blueprint.ts`:
- Around line 331-335: Normalize step.exit_condition by calling stripRef once
into a local variable (e.g., normalizedRid = stripRef(step.exit_condition)) and
use that normalizedRid when calling findBlockByRid and when comparing against
stripped specConditions (replace the current findBlockByRid(step.exit_condition)
and stripRef(c.rid) === step.exit_condition check to use normalizedRid), so
lookups succeed whether exit_condition includes a $ref prefix or not.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e569f41 and c1bb5a2.

📒 Files selected for processing (5)
  • multi-agent/api/flask/endpoints/blueprints.py
  • multi-agent/blueprints/service.py
  • ui/client/src/components/agentic-ai/graphs/GraphHeader.tsx
  • ui/client/src/hooks/use-graph-logic.ts
  • ui/client/src/hooks/use-load-blueprint.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/client/src/components/agentic-ai/graphs/GraphHeader.tsx
  • multi-agent/api/flask/endpoints/blueprints.py

Comment on lines 52 to 53
except KeyError:
raise BlueprintNotFoundError(blueprint_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Chain the re-raised exception per PEP 3134 / Ruff B904.

Raising inside an except clause without explicit chaining sets __context__ implicitly but leaves __cause__ unset, making tracebacks ambiguous. Since this is a clean domain-boundary translation (repository KeyError → service BlueprintNotFoundError), suppress the chain with from None to avoid leaking repository internals, or chain with from err to preserve the full traceback.

🐛 Proposed fix (suppress internal chain)
-        except KeyError:
-            raise BlueprintNotFoundError(blueprint_id)
+        except KeyError as err:
+            raise BlueprintNotFoundError(blueprint_id) from None

Or, to preserve the full traceback for debugging:

-        except KeyError:
-            raise BlueprintNotFoundError(blueprint_id)
+        except KeyError as err:
+            raise BlueprintNotFoundError(blueprint_id) from err
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except KeyError:
raise BlueprintNotFoundError(blueprint_id)
except KeyError as err:
raise BlueprintNotFoundError(blueprint_id) from None
🧰 Tools
🪛 Ruff (0.15.2)

[warning] 53-53: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@multi-agent/blueprints/service.py` around lines 52 - 53, The current except
block re-raises BlueprintNotFoundError from a caught KeyError without explicit
chaining; change the handler to "except KeyError as err:" and re-raise with
explicit suppression of the original context to avoid leaking repository
internals by using "raise BlueprintNotFoundError(blueprint_id) from None"
(update the except block around BlueprintNotFoundError/KeyError in service.py).

Comment on lines +640 to +642
if (!editBlueprintId || isLoadingBlocks || blueprintLoadedRef.current) return;
blueprintLoadedRef.current = true;

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Track loaded blueprint by ID instead of a boolean guard.

At Line 640 and Line 641, blueprintLoadedRef.current is a one-shot lock. If editBlueprintId changes while this hook stays mounted, the new blueprint is never loaded, but save still uses the new ID at Line 1110. That can overwrite the wrong blueprint with stale canvas data.

🔧 Proposed fix
-  const blueprintLoadedRef = useRef(false);
+  const loadedBlueprintIdRef = useRef<string | null>(null);

   useEffect(() => {
-    if (!editBlueprintId || isLoadingBlocks || blueprintLoadedRef.current) return;
-    blueprintLoadedRef.current = true;
+    if (!editBlueprintId || isLoadingBlocks) return;
+    if (loadedBlueprintIdRef.current === editBlueprintId) return;
+    loadedBlueprintIdRef.current = editBlueprintId;

     loadBlueprintForEditing(
       editBlueprintId,
       allBlocksData,
       conditionsData,
       conditionEdgeColor,
     )
@@
       .catch((err) => {
         console.error("Failed to load blueprint for editing:", err);
+        loadedBlueprintIdRef.current = null;
         setIsEditMode(false);
         setEditBlueprintName("");
         setEditBlueprintDescription("");
         toast({
@@
         initializeDefaultNodes();
       });
   }, [editBlueprintId, isLoadingBlocks]);
+
+  useEffect(() => {
+    if (!editBlueprintId) {
+      loadedBlueprintIdRef.current = null;
+    }
+  }, [editBlueprintId]);

Also applies to: 668-680

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/client/src/hooks/use-graph-logic.ts` around lines 640 - 642, Replace the
one-shot boolean guard blueprintLoadedRef.current with a ref that tracks the
last loaded blueprint ID: change blueprintLoadedRef to something like
lastLoadedBlueprintIdRef and update the guard in the useGraphLogic hook to
return early when lastLoadedBlueprintIdRef.current === editBlueprintId (also
include checks for !editBlueprintId and isLoadingBlocks), then set
lastLoadedBlueprintIdRef.current = editBlueprintId after loading; apply the same
ID-based guard changes to the other block-loading logic around the 668-680
region so new editBlueprintId values trigger reloads and avoid saving stale
canvas data with the wrong editBlueprintId.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
ui/client/src/hooks/use-load-blueprint.ts (1)

8-28: Consider tightening any types in exported interfaces.

config?: any and branches?: any are part of the public API surface exported from this module. Downstream consumers that pattern-match on these fields have no type guidance. At minimum, config could be Record<string, unknown> and branches could be Record<string, string>.

♻️ Proposed refinement
 export interface YamlFlowPlanStep {
   uid: string;
   node: string;
   after?: string | string[] | null;
-  branches?: any;
+  branches?: Record<string, string>;
   exit_condition?: string;
 }
 
 export interface YamlFlowNode {
   rid: string;
   name: string;
   type?: string;
-  config?: any;
+  config?: Record<string, unknown>;
 }
 
 export interface YamlFlowCondition {
   rid: string;
   name: string;
   type?: string;
-  config?: any;
+  config?: Record<string, unknown>;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/client/src/hooks/use-load-blueprint.ts` around lines 8 - 28, The exported
interfaces YamlFlowNode and YamlFlowCondition currently use config?: any and
YamlFlowPlanStep uses config?: any and branches?: any; replace these broad any
types with stricter shapes (e.g. config?: Record<string, unknown> for
node/condition/step and branches?: Record<string, string> for YamlFlowPlanStep)
to provide downstream consumers type guidance while preserving optionality;
update the type annotations for config and branches in the interfaces
YamlFlowNode, YamlFlowCondition, and YamlFlowPlanStep accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/client/src/hooks/use-load-blueprint.ts`:
- Around line 409-426: The conditional edge pushed into reactFlowEdges (in the
block that creates an edge with id `${step.uid}-${targetUid}-${branch}` and
data.isConditional) omits width/height on its markerEnd, causing inconsistent
arrow size; update that markerEnd object (the same place where
MarkerType.ArrowClosed is set) to include width: 20 and height: 20 so it matches
the regular edges' marker size.

---

Nitpick comments:
In `@ui/client/src/hooks/use-load-blueprint.ts`:
- Around line 8-28: The exported interfaces YamlFlowNode and YamlFlowCondition
currently use config?: any and YamlFlowPlanStep uses config?: any and branches?:
any; replace these broad any types with stricter shapes (e.g. config?:
Record<string, unknown> for node/condition/step and branches?: Record<string,
string> for YamlFlowPlanStep) to provide downstream consumers type guidance
while preserving optionality; update the type annotations for config and
branches in the interfaces YamlFlowNode, YamlFlowCondition, and YamlFlowPlanStep
accordingly.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1bb5a2 and fcc42cc.

📒 Files selected for processing (2)
  • multi-agent/blueprints/service.py
  • ui/client/src/hooks/use-load-blueprint.ts

Comment on lines +409 to +426
reactFlowEdges.push({
id: `${step.uid}-${targetUid}-${branch}`,
source: step.uid,
target: targetUid as string,
type: "custom",
style: { strokeDasharray: "5,5", stroke: conditionEdgeColor },
markerEnd: {
type: MarkerType.ArrowClosed,
color: conditionEdgeColor,
},
data: {
branch: String(branch),
isConditional: true,
},
label: String(branch),
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Conditional edge markerEnd is missing width/height, causing an inconsistent arrow size.

Regular edges (lines 393–398) explicitly set width: 20, height: 20 on their markerEnd. The conditional edge markerEnd omits these, so the arrowhead will render at the reactflow default size rather than matching the regular edge style.

🐛 Proposed fix
         reactFlowEdges.push({
           id: `${step.uid}-${targetUid}-${branch}`,
           source: step.uid,
           target: targetUid as string,
           type: "custom",
           style: { strokeDasharray: "5,5", stroke: conditionEdgeColor },
           markerEnd: {
             type: MarkerType.ArrowClosed,
             color: conditionEdgeColor,
+            width: 20,
+            height: 20,
           },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/client/src/hooks/use-load-blueprint.ts` around lines 409 - 426, The
conditional edge pushed into reactFlowEdges (in the block that creates an edge
with id `${step.uid}-${targetUid}-${branch}` and data.isConditional) omits
width/height on its markerEnd, causing inconsistent arrow size; update that
markerEnd object (the same place where MarkerType.ArrowClosed is set) to include
width: 20 and height: 20 so it matches the regular edges' marker size.

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.

1 participant