feat(workflows): add sub-workflow inspector, breadcrumb navigation, and reference UI

Phase 3 frontend: sub-workflow node inspector with reference/inline mode toggle,
breadcrumb drill-down navigation for nested workflows, read-only view for
referenced workflows, inline workflow editing with stack propagation,
sub-workflow label badges on canvas nodes, and referential integrity error
display on delete.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-04-05 19:44:02 +02:00
co-authored by Copilot
parent 41e74c2fa9
commit 871609db5b
7 changed files with 523 additions and 27 deletions
@@ -18,10 +18,12 @@ import type {
} from '@shared/domain/workflow';
import { ModelSelect, ReasoningEffortSelect } from '@renderer/components/AgentConfigFields';
import { ConditionEditor } from '@renderer/components/workflow/ConditionEditor';
import { SubWorkflowInspector } from '@renderer/components/workflow/SubWorkflowInspector';
interface WorkflowGraphInspectorProps {
availableModels: ReadonlyArray<ModelDefinition>;
workflow: WorkflowDefinition;
workflows: ReadonlyArray<WorkflowDefinition>;
selectedNodeId: string | null;
selectedEdgeId: string | null;
validationIssues?: WorkflowValidationIssue[];
@@ -30,6 +32,7 @@ interface WorkflowGraphInspectorProps {
onNodeRemove: (nodeId: string) => void;
onEdgeChange: (edgeId: string, patch: Partial<WorkflowEdge>) => void;
onEdgeRemove: (edgeId: string) => void;
onDrillIntoSubWorkflow: (node: WorkflowNode) => void;
}
function InputField({
@@ -375,6 +378,7 @@ function EdgeInspector({
export function WorkflowGraphInspector({
availableModels,
workflow,
workflows,
selectedNodeId,
selectedEdgeId,
validationIssues,
@@ -383,6 +387,7 @@ export function WorkflowGraphInspector({
onNodeRemove,
onEdgeChange,
onEdgeRemove,
onDrillIntoSubWorkflow,
}: WorkflowGraphInspectorProps) {
const selectedNode = selectedNodeId
? workflow.graph.nodes.find((n) => n.id === selectedNodeId)
@@ -436,6 +441,22 @@ export function WorkflowGraphInspector({
);
}
if (selectedNode.kind === 'sub-workflow') {
return (
<div className="p-4">
<SubWorkflowInspector
currentWorkflowId={workflow.id}
node={selectedNode}
onDrillIntoSubWorkflow={onDrillIntoSubWorkflow}
onNodeChange={onNodeChange}
onNodeConfigChange={onNodeConfigChange}
onNodeRemove={onNodeRemove}
workflows={workflows}
/>
</div>
);
}
return (
<div className="p-4">
<PlaceholderNodeInspector