summaryrefslogtreecommitdiff
path: root/frontend/src/store/flowStore.ts
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/store/flowStore.ts')
-rw-r--r--frontend/src/store/flowStore.ts78
1 files changed, 78 insertions, 0 deletions
diff --git a/frontend/src/store/flowStore.ts b/frontend/src/store/flowStore.ts
index 6083a36..d2114aa 100644
--- a/frontend/src/store/flowStore.ts
+++ b/frontend/src/store/flowStore.ts
@@ -68,6 +68,11 @@ interface FlowState {
getActiveContext: (nodeId: string) => Message[];
+ // Actions
+ deleteEdge: (edgeId: string) => void;
+ deleteNode: (nodeId: string) => void;
+ deleteBranch: (startNodeId?: string, startEdgeId?: string) => void;
+
propagateTraces: () => void;
}
@@ -196,6 +201,79 @@ const useFlowStore = create<FlowState>((set, get) => ({
return contextMessages;
},
+ deleteEdge: (edgeId: string) => {
+ set({
+ edges: get().edges.filter(e => e.id !== edgeId)
+ });
+ get().propagateTraces();
+ },
+
+ deleteNode: (nodeId: string) => {
+ set({
+ nodes: get().nodes.filter(n => n.id !== nodeId),
+ edges: get().edges.filter(e => e.source !== nodeId && e.target !== nodeId)
+ });
+ get().propagateTraces();
+ },
+
+ deleteBranch: (startNodeId?: string, startEdgeId?: string) => {
+ const { edges, nodes } = get();
+ // We ONLY delete edges, NOT nodes.
+ const edgesToDelete = new Set<string>();
+
+ // Helper to traverse downstream EDGES based on Trace Dependency
+ const traverse = (currentEdge: Edge) => {
+ if (edgesToDelete.has(currentEdge.id)) return;
+ edgesToDelete.add(currentEdge.id);
+
+ const targetNodeId = currentEdge.target;
+ // Identify the trace ID carried by this edge
+ const traceId = currentEdge.sourceHandle?.replace('trace-', '');
+ if (!traceId) return;
+
+ // Look for outgoing edges from the target node that carry the EVOLUTION of this trace.
+ // Our logic generates next trace ID as: `${traceId}_${targetNodeId}`
+ const expectedNextTraceId = `${traceId}_${targetNodeId}`;
+
+ const outgoing = edges.filter(e => e.source === targetNodeId);
+ outgoing.forEach(nextEdge => {
+ // If the outgoing edge carries the evolved trace, delete it too
+ if (nextEdge.sourceHandle === `trace-${expectedNextTraceId}`) {
+ traverse(nextEdge);
+ }
+ });
+ };
+
+ if (startNodeId) {
+ // If deleting a node, we delete ALL outgoing edges recursively.
+ // Because all traces passing through this node are broken.
+ // But we can't use `traverse` directly because we don't have a single start edge.
+ // We just start traverse on ALL outgoing edges of this node.
+ const initialOutgoing = edges.filter(e => e.source === startNodeId);
+ initialOutgoing.forEach(e => traverse(e));
+
+ // Also delete incoming to this node
+ const incomingToNode = edges.filter(e => e.target === startNodeId);
+ incomingToNode.forEach(e => edgesToDelete.add(e.id));
+
+ set({
+ nodes: nodes.filter(n => n.id !== startNodeId),
+ edges: edges.filter(e => !edgesToDelete.has(e.id))
+ });
+ } else if (startEdgeId) {
+ const startEdge = edges.find(e => e.id === startEdgeId);
+ if (startEdge) {
+ traverse(startEdge);
+ }
+
+ set({
+ edges: edges.filter(e => !edgesToDelete.has(e.id))
+ });
+ }
+
+ get().propagateTraces();
+ },
+
propagateTraces: () => {
const { nodes, edges } = get();