From 2b0d629d45f8612d95a2656cd7ecd6c4b13b1174 Mon Sep 17 00:00:00 2001 From: Martin Vu <22mvu7@gmail.com> Date: Wed, 5 Aug 2026 18:31:57 -0700 Subject: [PATCH 1/2] fix(agent-service): remove dangling links when input ports shrink --- .../src/agent/workflow-state.spec.ts | 24 +++++++++++++++++++ agent-service/src/agent/workflow-state.ts | 12 ++++++++++ 2 files changed, 36 insertions(+) diff --git a/agent-service/src/agent/workflow-state.spec.ts b/agent-service/src/agent/workflow-state.spec.ts index 2fd27af6527..3c17b352def 100644 --- a/agent-service/src/agent/workflow-state.spec.ts +++ b/agent-service/src/agent/workflow-state.spec.ts @@ -341,6 +341,30 @@ describe("WorkflowState - updateOperatorInputPorts", () => { test("returns false for a missing operator", () => { expect(new WorkflowState().updateOperatorInputPorts("missing", 2)).toBe(false); }); + + test("removes links targeting input ports that are dropped", () => { + const state = new WorkflowState(); + + state.addOperator(makeOperator("src")); + state.addOperator( + makeOperator("op1", { + inputPorts: [ + { portID: "input-0", displayName: "Input 0" }, + { portID: "input-1", displayName: "Input 1" }, + ], + }) + ); + + state.addLink({ + linkID: "l1", + source: { operatorID: "src", portID: "output-0" }, + target: { operatorID: "op1", portID: "input-1" }, + }); + + state.updateOperatorInputPorts("op1", 1); + + expect(state.getAllLinks().map(l => l.linkID)).toEqual([]); + }); }); describe("WorkflowState - workflow content round-trip", () => { diff --git a/agent-service/src/agent/workflow-state.ts b/agent-service/src/agent/workflow-state.ts index 04ad2b0e4e8..9f41d3a0e1c 100644 --- a/agent-service/src/agent/workflow-state.ts +++ b/agent-service/src/agent/workflow-state.ts @@ -189,6 +189,18 @@ export class WorkflowState { inputPorts: newInputPorts, }; this.operators.set(operatorId, updatedOperator); + + const validInputPorts = new Set(newInputPorts.map(port => port.portID)); + + for (const link of this.getAllLinks()) { + if ( + link.target.operatorID === operatorId && + !validInputPorts.has(link.target.portID) + ) { + this.deleteLink(link.linkID); + } + } + this.operatorPropertyChangeSubject.next({ operator: updatedOperator }); return true; } From 045a9fedf4732bf1bd55e1ca3cde44af7dbe668a Mon Sep 17 00:00:00 2001 From: Martin Vu <22mvu7@gmail.com> Date: Wed, 5 Aug 2026 18:49:20 -0700 Subject: [PATCH 2/2] style(agent-service): format workflow-state --- agent-service/src/agent/workflow-state.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/agent-service/src/agent/workflow-state.ts b/agent-service/src/agent/workflow-state.ts index 9f41d3a0e1c..4e78ee88e58 100644 --- a/agent-service/src/agent/workflow-state.ts +++ b/agent-service/src/agent/workflow-state.ts @@ -193,10 +193,7 @@ export class WorkflowState { const validInputPorts = new Set(newInputPorts.map(port => port.portID)); for (const link of this.getAllLinks()) { - if ( - link.target.operatorID === operatorId && - !validInputPorts.has(link.target.portID) - ) { + if (link.target.operatorID === operatorId && !validInputPorts.has(link.target.portID)) { this.deleteLink(link.linkID); } }