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); }); });