Skip to content

Commit c81983d

Browse files
authored
Workflows v2: Enhanced Task Management and Control System (#221)
# Workflows v2: Enhanced Task Management and Control System This major update introduces a sophisticated workflow management system with powerful new capabilities for task orchestration and execution control. Key features include: ## 🎮 Advanced Workflow Controls - Pause/Resume functionality for fine-grained workflow management - Immediate workflow termination with proper cleanup - Enhanced state management for workflow interruptions ## 🔄 Task Management Improvements - New TaskManager for better task lifecycle handling - Deterministic execution patterns support: - Sequential execution - Dependency-based execution - Parallel task processing - Improved task status tracking and feedback mechanisms ## 🛠 Technical Enhancements - Integration of `dependency-graph` for robust task dependency management - Enhanced ESLint configurations and Jest test patterns - Streamlined error handling with specialized abort controllers - Comprehensive test coverage with updated snapshots ## 📊 Developer Experience - Better debugging capabilities through enhanced logging - Improved workflow state visibility - More predictable task execution patterns - Cleaner codebase structure with removed redundant components ## 🙏 Special Thanks - **@anthonydevs17** for implementing the core pause/resume functionality and workflow control features - **@ernestocarrasco** for the task management refactoring and test suite improvements This update represents a significant step forward in KaibanJS's workflow management capabilities, providing developers with more control and visibility over their agent-based workflows while maintaining robustness and predictability. [Source: PR #221](#221)
2 parents eb9657b + 04b2aa5 commit c81983d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+57187
-1499
lines changed

eslint.config.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export default [
4646
'@typescript-eslint/no-require-imports': 'off',
4747
'react/react-in-jsx-scope': 'off',
4848
'react/prop-types': 'off',
49+
'jest/no-focused-tests': 'off',
50+
'jest/no-disabled-tests': 'off',
4951
},
5052
},
5153
];

jest.config.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,5 @@ module.exports = {
99
testEnvironment: 'node', // Use Node.js environment for executing tests,
1010
verbose: true, // Make Jest more verbose
1111
silent: false, // Ensure Jest is not silent (though this is not directly related to console.log output)
12-
// testMatch: [
13-
// "**/tests/e2e/exampl/**/*.js"
14-
// ], // Run tests only in the specific directory
12+
// testMatch: ['**/tests/e2e/**/eventPlanningTeam.test.js'], // Run tests only in the specific directory
1513
};

package-lock.json

Lines changed: 1919 additions & 827 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"test:watch": "TEST_ENV=mocked-llm-apis jest --testPathPattern='tests/e2e' --watch",
3434
"test:debug": "TEST_ENV=mocked-llm-apis node --inspect-brk node_modules/.bin/jest --runInBand --verbose --testPathPattern='tests/e2e'",
3535
"test:prod": "npm run build && jest --testPathPattern='tests/e2e'",
36-
"test:integration": "TEST_ENV=mocked-llm-apis jest --testPathPattern='tests/e2e'",
36+
"test:integration": "TEST_ENV=mocked-llm-apis jest --testPathPattern='tests/e2e' --verbose",
3737
"test:e2e": "TEST_ENV=real-llm-apis jest --testPathPattern='tests/e2e'",
3838
"test:unit": "jest --testPathPattern='tests/unit' --watch",
3939
"test:unit:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --verbose --testPathPattern='tests/unit'",
@@ -96,12 +96,13 @@
9696
"@telemetrydeck/sdk": "^2.0.4",
9797
"ansis": "^3.3.2",
9898
"chalk": "^5.3.0",
99+
"dependency-graph": "^1.0.0",
99100
"dotenv": "^16.4.5",
100101
"figlet": "^1.7.0",
101102
"langchain": "0.2.10",
102103
"loglevel": "^1.9.1",
103104
"ora": "^8.1.0",
104-
"p-queue": "^8.0.1",
105+
"p-queue": "^8.1.0",
105106
"readline": "^1.3.0",
106107
"uuid": "10.0.0",
107108
"zod-to-json-schema": "^3.23.2",

packages/tools/src/_utils/AgentWithToolPreviewer.jsx

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ export const AgentWithToolPreviewer = ({ team }) => {
7373
}
7474
};
7575

76+
const handlePauseResume = async () => {
77+
try {
78+
if (teamWorkflowStatus === 'PAUSED') {
79+
team.resume();
80+
} else {
81+
team.pause();
82+
}
83+
} catch (error) {
84+
console.error('Error pausing/resuming workflow:', error);
85+
}
86+
};
87+
88+
const handleStop = async () => {
89+
try {
90+
team.stop();
91+
} catch (error) {
92+
console.error('Error stopping workflow:', error);
93+
}
94+
};
95+
7696
if (!agents || agents.length === 0) {
7797
return <div className="no-team-message">No agents available</div>;
7898
}
@@ -130,13 +150,34 @@ export const AgentWithToolPreviewer = ({ team }) => {
130150
rows={5}
131151
spellCheck="false"
132152
/>
133-
<button
134-
className={`start-button ${teamWorkflowStatus.toLowerCase()}`}
135-
onClick={handleStartTeam}
136-
disabled={teamWorkflowStatus === 'RUNNING'}
137-
>
138-
{teamWorkflowStatus === 'RUNNING' ? 'Running...' : 'Start Team'}
139-
</button>
153+
<div className="workflow-buttons">
154+
<button
155+
className={`start-button ${teamWorkflowStatus.toLowerCase()}`}
156+
onClick={handleStartTeam}
157+
disabled={
158+
teamWorkflowStatus === 'RUNNING' ||
159+
teamWorkflowStatus === 'PAUSED'
160+
}
161+
>
162+
{teamWorkflowStatus === 'RUNNING' ? 'Running...' : 'Start Team'}
163+
</button>
164+
165+
<button
166+
className={`pause-resume-button ${teamWorkflowStatus.toLowerCase()}`}
167+
onClick={handlePauseResume}
168+
disabled={!['RUNNING', 'PAUSED'].includes(teamWorkflowStatus)}
169+
>
170+
{teamWorkflowStatus === 'PAUSED' ? 'Resume' : 'Pause'}
171+
</button>
172+
173+
<button
174+
className={`stop-button ${teamWorkflowStatus.toLowerCase()}`}
175+
onClick={handleStop}
176+
disabled={!['RUNNING', 'PAUSED'].includes(teamWorkflowStatus)}
177+
>
178+
Stop
179+
</button>
180+
</div>
140181
</div>
141182

142183
<div className="workflow-status">

packages/tools/src/_utils/tools_agent_preview.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,33 @@ pre {
248248
.status-using_tool_end {
249249
color: #2e7d32;
250250
}
251+
252+
.workflow-buttons {
253+
display: flex;
254+
gap: 10px;
255+
margin-top: 10px;
256+
}
257+
258+
.pause-resume-button,
259+
.stop-button {
260+
padding: 8px 16px;
261+
border-radius: 4px;
262+
border: 1px solid #ccc;
263+
cursor: pointer;
264+
}
265+
266+
.pause-resume-button:disabled,
267+
.stop-button:disabled {
268+
opacity: 0.5;
269+
cursor: not-allowed;
270+
}
271+
272+
.pause-resume-button {
273+
background-color: #f0ad4e;
274+
color: white;
275+
}
276+
277+
.stop-button {
278+
background-color: #d9534f;
279+
color: white;
280+
}

playground/react/src/AgentsBoardDebugger.jsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,23 @@ const AgentsBoardDebugger = ({ team, title = null }) => {
152152
<button className="actionButton" onClick={startTeam}>
153153
Start Workflow
154154
</button>
155-
155+
<button
156+
className="actionButton"
157+
onClick={() => {
158+
if (teamWorkflowStatus === 'PAUSED') {
159+
team.resume();
160+
} else if (teamWorkflowStatus === 'RUNNING') {
161+
team.pause();
162+
}
163+
}}
164+
>
165+
{teamWorkflowStatus === 'PAUSED'
166+
? 'Resume Workflow'
167+
: 'Pause Workflow'}
168+
</button>
169+
<button className="actionButton" onClick={() => team.stop()}>
170+
Stop Workflow
171+
</button>
156172
{teamWorkflowStatus === 'running_workflow' && <Spinner />}
157173
</div>
158174
</div>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import AgentsBoardDebugger from '../AgentsBoardDebugger';
2+
import teamSequential from '../teams/event_planning/openai';
3+
import teamParallel from '../teams/event_planning/openai_parallel';
4+
import teamMixed from '../teams/event_planning/openai_mixed';
5+
import '../index.css';
6+
7+
export default {
8+
title: 'Features/Task Chaining',
9+
component: AgentsBoardDebugger,
10+
};
11+
12+
export const SequentialEventPlanning = {
13+
args: {
14+
team: teamSequential,
15+
title: 'Event Planning with Sequential Tasks',
16+
},
17+
};
18+
19+
export const ParallelEventPlanning = {
20+
args: {
21+
team: teamParallel,
22+
title: 'Event Planning with Parallel Tasks',
23+
},
24+
};
25+
26+
export const MixedEventPlanning = {
27+
args: {
28+
team: teamMixed,
29+
title: 'Event Planning with Mixed Task Dependencies',
30+
},
31+
};

0 commit comments

Comments
 (0)