Skip to content

Commit 0cd2e18

Browse files
Merge pull request #14 from CodeSignal/remove-end-button
Remove end node
2 parents 1d7016b + 86d0637 commit 0cd2e18

File tree

8 files changed

+40
-19
lines changed

8 files changed

+40
-19
lines changed

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Project Overview
66

7-
Visual workflow builder for agentic LLM pipelines. Users drag-and-drop nodes (Start, Agent, If/Else, Approval, End) onto a canvas, connect them, configure LLM prompts and branching logic, then execute workflows server-side against OpenAI. Run results are persisted as JSON audit trails.
7+
Visual workflow builder for agentic LLM pipelines. Users drag-and-drop nodes (Start, Agent, If/Else, Approval) onto a canvas, connect them, configure LLM prompts and branching logic, then execute workflows server-side against OpenAI. Run results are persisted as JSON audit trails.
88

99
## Monorepo Layout
1010

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Agentic Workflow Builder
22

3-
Agentic Workflow Builder is a web app for visually composing, executing, and auditing LLM workflows. Drag Start, Agent, If/Else, Approval, and End nodes onto the canvas, connect them with Bezier edges, configure prompts inline, and run the flow through a server-side engine that records every step for later review.
3+
Agentic Workflow Builder is a web app for visually composing, executing, and auditing LLM workflows. Drag Start, Agent, If/Else, and Approval nodes onto the canvas, connect them with Bezier edges, configure prompts inline, and run the flow through a server-side engine that records every step for later review.
44

55
## Repository Layout
66

apps/web/index.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ <h3>Nodes</h3>
3939
<div class="draggable-node" draggable="true" data-type="approval">
4040
<span class="icon icon-chermark-badge icon-primary"></span>User Approval
4141
</div>
42-
<div class="draggable-node" draggable="true" data-type="end">
43-
<span class="icon icon-rectangle-2698 icon-primary"></span>End
44-
</div>
4542
</div>
4643
</div>
4744
<div class="canvas-controls">
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { describe, expect, it, vi } from 'vitest';
2+
3+
import { WorkflowEditor } from './workflow-editor';
4+
5+
describe('WorkflowEditor renderPorts', () => {
6+
it('renders an output port for start nodes', () => {
7+
const renderPorts = (
8+
WorkflowEditor.prototype as unknown as {
9+
renderPorts: (
10+
node: { id: string; type: string },
11+
el: { appendChild: (port: { handle: string }) => void }
12+
) => void;
13+
}
14+
).renderPorts;
15+
const createPort = vi.fn((_nodeId: string, handle: string) => ({ handle }));
16+
const appended: Array<{ handle: string }> = [];
17+
const element = {
18+
appendChild: (port: { handle: string }) => {
19+
appended.push(port);
20+
}
21+
};
22+
23+
renderPorts.call(
24+
{ createPort, getNodeHeaderPortTop: () => 24 },
25+
{ id: 'node_start', type: 'start' },
26+
element
27+
);
28+
29+
expect(createPort).toHaveBeenCalledTimes(1);
30+
expect(createPort).toHaveBeenCalledWith('node_start', 'output', 'port-out', 'Next step', 24);
31+
expect(appended).toEqual([{ handle: 'output' }]);
32+
});
33+
});

apps/web/src/app/workflow-editor.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,7 +1722,6 @@ export class WorkflowEditor {
17221722
case 'approval':
17231723
return { prompt: 'Review and approve this step.', collapsed: true };
17241724
case 'start':
1725-
case 'end':
17261725
return { collapsed: true };
17271726
default:
17281727
return { collapsed: true };
@@ -1802,7 +1801,7 @@ export class WorkflowEditor {
18021801

18031802
if (!node.data) node.data = {};
18041803
if (node.data.collapsed === undefined) {
1805-
node.data.collapsed = node.type === 'start' || node.type === 'end';
1804+
node.data.collapsed = node.type === 'start';
18061805
}
18071806
const hasSettings = this.nodeHasSettings(node);
18081807
el.classList.toggle('expanded', !node.data.collapsed);
@@ -1954,7 +1953,6 @@ export class WorkflowEditor {
19541953
return `<span class="icon icon-robot icon-primary"></span>${escapeHtml(name)}`;
19551954
}
19561955
if (node.type === 'start') return '<span class="icon icon-lesson-introduction icon-primary"></span>Start';
1957-
if (node.type === 'end') return '<span class="icon icon-rectangle-2698 icon-primary"></span>End';
19581956
if (node.type === 'if') return '<span class="icon icon-path icon-primary"></span>Condition';
19591957
if (node.type === 'approval') return '<span class="icon icon-chermark-badge icon-primary"></span>User Approval';
19601958
return `<span class="icon icon-primary"></span>${node.type}`;
@@ -2313,13 +2311,11 @@ export class WorkflowEditor {
23132311
}
23142312

23152313
if (node.type !== 'start') {
2316-
const inputTooltip = node.type === 'end' ? 'End input' : 'Input';
2317-
const portIn = this.createPort(node.id, 'input', 'port-in', inputTooltip, this.getNodeHeaderPortTop(node));
2314+
const portIn = this.createPort(node.id, 'input', 'port-in', 'Input', this.getNodeHeaderPortTop(node));
23182315
el.appendChild(portIn);
23192316
}
23202317

2321-
if (node.type !== 'end') {
2322-
if (node.type === 'if') {
2318+
if (node.type === 'if') {
23232319
const conditions = this.getIfConditions(node);
23242320
if (this.shouldAggregateCollapsedIfPorts(node)) {
23252321
const aggregateConditionPort = this.createPort(
@@ -2399,7 +2395,6 @@ export class WorkflowEditor {
23992395
const outputTooltip = node.type === 'start' ? 'Next step' : 'Output';
24002396
el.appendChild(this.createPort(node.id, 'output', 'port-out', outputTooltip, this.getNodeHeaderPortTop(node)));
24012397
}
2402-
}
24032398
}
24042399

24052400
createPort(

apps/web/src/data/help-content.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const helpContent = `
1212
1313
<section id="overview">
1414
<h2>Overview</h2>
15-
<p>The Agentic Workflow Builder lets you compose agent flows with Start, Agent, Condition, Approval, and End nodes. Drag nodes, connect them, configure prompts, and run against the server-side workflow engine.</p>
15+
<p>The Agentic Workflow Builder lets you compose agent flows with Start, Agent, Condition, and Approval nodes. Drag nodes, connect them, configure prompts, and run against the server-side workflow engine.</p>
1616
</section>
1717
1818
<section id="getting-started">

packages/types/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type NodeType = 'start' | 'agent' | 'if' | 'approval' | 'end' | string;
1+
export type NodeType = 'start' | 'agent' | 'if' | 'approval' | string;
22

33
export interface BaseNodeData {
44
collapsed?: boolean;

packages/workflow-engine/src/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,6 @@ export class WorkflowEngine {
339339
this.waitingForInput = true;
340340
this.log(node.id, 'wait_input', 'Waiting for user approval');
341341
return undefined;
342-
case 'end':
343-
return undefined;
344342
default:
345343
this.log(node.id, 'warn', `Unknown node type "${node.type}" skipped`);
346344
}
@@ -456,8 +454,6 @@ export class WorkflowEngine {
456454
return 'condition node';
457455
case 'approval':
458456
return 'approval node';
459-
case 'end':
460-
return 'end node';
461457
default:
462458
return `${node.type} node`;
463459
}

0 commit comments

Comments
 (0)