diff --git a/src/renderer/components/PatternEditor.tsx b/src/renderer/components/PatternEditor.tsx
index 2ce7764..f4c4efa 100644
--- a/src/renderer/components/PatternEditor.tsx
+++ b/src/renderer/components/PatternEditor.tsx
@@ -18,6 +18,8 @@ import {
import type { ApprovalCheckpointKind, ApprovalPolicy } from '@shared/domain/approval';
import type { ModelDefinition } from '@shared/domain/models';
import {
+ addAgentToGraph,
+ removeAgentFromGraph,
resolvePatternGraph,
syncPatternGraph,
validatePatternDefinition,
@@ -35,7 +37,6 @@ import {
} from '@shared/domain/tooling';
import { ToggleSwitch } from '@renderer/components/ui';
-import { addAgentNodeToGraph } from '@renderer/lib/patternGraph';
import { PatternGraphCanvas } from './pattern-graph/PatternGraphCanvas';
import { PatternGraphInspector } from './pattern-graph/PatternGraphInspector';
@@ -143,6 +144,10 @@ export function PatternEditor({
const graph = resolvePatternGraph(pattern);
function emitChange(nextPattern: PatternDefinition) {
+ onChange({ ...nextPattern, graph: resolvePatternGraph(nextPattern) });
+ }
+
+ function emitModeChange(nextPattern: PatternDefinition) {
onChange(syncPatternGraph(nextPattern));
}
@@ -159,7 +164,7 @@ export function PatternEditor({
model: 'gpt-5.4',
reasoningEffort: 'high',
};
- const updatedGraph = addAgentNodeToGraph(graph, newAgent);
+ const updatedGraph = addAgentToGraph(graph, pattern.mode, newAgent);
onChange({ ...pattern, agents: [...pattern.agents, newAgent], graph: updatedGraph });
}
@@ -175,9 +180,11 @@ export function PatternEditor({
return;
}
- emitChange({
+ const updatedGraph = removeAgentFromGraph(graph, pattern.mode, agentId);
+ onChange({
...pattern,
agents: pattern.agents.filter((a) => a.id !== agentId),
+ graph: updatedGraph,
});
setSelectedNodeId(null);
}
@@ -374,7 +381,7 @@ export function PatternEditor({
}`}
disabled={disabled}
key={mode}
- onClick={() => emitChange({ ...pattern, mode })}
+ onClick={() => emitModeChange({ ...pattern, mode })}
type="button"
>
diff --git a/src/renderer/lib/patternGraph.ts b/src/renderer/lib/patternGraph.ts
index 8cd38a9..ee0e578 100644
--- a/src/renderer/lib/patternGraph.ts
+++ b/src/renderer/lib/patternGraph.ts
@@ -246,32 +246,6 @@ export function removeEdge(graph: PatternGraph, removeEdgeId: string): PatternGr
return { ...graph, edges: graph.edges.filter((e) => e.id !== removeEdgeId) };
}
-/* ── Add disconnected agent node ───────────────────────────── */
-
-export function addAgentNodeToGraph(
- graph: PatternGraph,
- agent: PatternAgentDefinition,
-): PatternGraph {
- const existingAgentNodes = graph.nodes.filter((n) => n.kind === 'agent');
- const nextOrder = existingAgentNodes.length;
-
- // Place new node below existing agent nodes
- const maxY = existingAgentNodes.reduce((max, n) => Math.max(max, n.position.y), 0);
- const avgX = existingAgentNodes.length > 0
- ? Math.round(existingAgentNodes.reduce((sum, n) => sum + n.position.x, 0) / existingAgentNodes.length)
- : 400;
-
- const newNode: PatternGraphNode = {
- id: `agent-node-${agent.id}`,
- kind: 'agent',
- agentId: agent.id,
- order: nextOrder,
- position: { x: avgX, y: maxY + 120 },
- };
-
- return { ...graph, nodes: [...graph.nodes, newNode] };
-}
-
/* ── Sequential reorder ────────────────────────────────────── */
export function swapSequentialOrder(
diff --git a/tests/renderer/patternGraph.test.ts b/tests/renderer/patternGraph.test.ts
index 235c10c..5483699 100644
--- a/tests/renderer/patternGraph.test.ts
+++ b/tests/renderer/patternGraph.test.ts
@@ -1,8 +1,7 @@
import { describe, expect, test } from 'bun:test';
-import { createBuiltinPatterns, resolvePatternGraph, type PatternDefinition } from '@shared/domain/pattern';
+import { addAgentToGraph, createBuiltinPatterns, resolvePatternGraph, type PatternDefinition } from '@shared/domain/pattern';
import {
- addAgentNodeToGraph,
addEdge,
autoLayoutGraph,
canMoveSequential,
@@ -208,20 +207,20 @@ describe('pattern graph mutation helpers', () => {
expect(updated.edges.find((e) => e.id === firstEdge.id)).toBeUndefined();
});
- test('addAgentNodeToGraph places a disconnected agent node on the canvas', () => {
+ test('addAgentToGraph inserts a wired agent node for sequential mode', () => {
const pattern = findPattern('sequential');
const graph = resolvePatternGraph(pattern);
const newAgent = { id: 'new-1', name: 'New Agent', description: '', instructions: '', model: 'gpt-5.4' };
- const updated = addAgentNodeToGraph(graph, newAgent);
+ const updated = addAgentToGraph(graph, pattern.mode, newAgent);
expect(updated.nodes.length).toBe(graph.nodes.length + 1);
const newNode = updated.nodes.find((n) => n.agentId === 'new-1');
expect(newNode).toBeDefined();
expect(newNode!.kind).toBe('agent');
- // No new edges added — node is disconnected
- expect(updated.edges.length).toBe(graph.edges.length);
+ // New agent is wired into the chain, so edge count stays at agents+1
+ expect(updated.edges.length).toBe(graph.edges.length + 1);
});
});