claude-flow 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +612 -0
  3. package/bin/claude-flow +0 -0
  4. package/bin/claude-flow-simple +0 -0
  5. package/bin/claude-flow-typecheck +0 -0
  6. package/deno.json +84 -0
  7. package/package.json +45 -0
  8. package/scripts/check-links.ts +274 -0
  9. package/scripts/check-performance-regression.ts +168 -0
  10. package/scripts/claude-sparc.sh +562 -0
  11. package/scripts/coverage-report.ts +692 -0
  12. package/scripts/demo-task-system.ts +224 -0
  13. package/scripts/install.js +72 -0
  14. package/scripts/test-batch-tasks.ts +29 -0
  15. package/scripts/test-coordination-features.ts +238 -0
  16. package/scripts/test-mcp.ts +251 -0
  17. package/scripts/test-runner.ts +571 -0
  18. package/scripts/validate-examples.ts +288 -0
  19. package/src/cli/cli-core.ts +273 -0
  20. package/src/cli/commands/agent.ts +83 -0
  21. package/src/cli/commands/config.ts +442 -0
  22. package/src/cli/commands/help.ts +765 -0
  23. package/src/cli/commands/index.ts +963 -0
  24. package/src/cli/commands/mcp.ts +191 -0
  25. package/src/cli/commands/memory.ts +74 -0
  26. package/src/cli/commands/monitor.ts +403 -0
  27. package/src/cli/commands/session.ts +595 -0
  28. package/src/cli/commands/start.ts +156 -0
  29. package/src/cli/commands/status.ts +345 -0
  30. package/src/cli/commands/task.ts +79 -0
  31. package/src/cli/commands/workflow.ts +763 -0
  32. package/src/cli/completion.ts +553 -0
  33. package/src/cli/formatter.ts +310 -0
  34. package/src/cli/index.ts +211 -0
  35. package/src/cli/main.ts +23 -0
  36. package/src/cli/repl.ts +1050 -0
  37. package/src/cli/simple-cli.js +211 -0
  38. package/src/cli/simple-cli.ts +211 -0
  39. package/src/coordination/README.md +400 -0
  40. package/src/coordination/advanced-scheduler.ts +487 -0
  41. package/src/coordination/circuit-breaker.ts +366 -0
  42. package/src/coordination/conflict-resolution.ts +490 -0
  43. package/src/coordination/dependency-graph.ts +475 -0
  44. package/src/coordination/index.ts +63 -0
  45. package/src/coordination/manager.ts +460 -0
  46. package/src/coordination/messaging.ts +290 -0
  47. package/src/coordination/metrics.ts +585 -0
  48. package/src/coordination/resources.ts +322 -0
  49. package/src/coordination/scheduler.ts +390 -0
  50. package/src/coordination/work-stealing.ts +224 -0
  51. package/src/core/config.ts +627 -0
  52. package/src/core/event-bus.ts +186 -0
  53. package/src/core/json-persistence.ts +183 -0
  54. package/src/core/logger.ts +262 -0
  55. package/src/core/orchestrator-fixed.ts +312 -0
  56. package/src/core/orchestrator.ts +1234 -0
  57. package/src/core/persistence.ts +276 -0
  58. package/src/mcp/auth.ts +438 -0
  59. package/src/mcp/claude-flow-tools.ts +1280 -0
  60. package/src/mcp/load-balancer.ts +510 -0
  61. package/src/mcp/router.ts +240 -0
  62. package/src/mcp/server.ts +548 -0
  63. package/src/mcp/session-manager.ts +418 -0
  64. package/src/mcp/tools.ts +180 -0
  65. package/src/mcp/transports/base.ts +21 -0
  66. package/src/mcp/transports/http.ts +457 -0
  67. package/src/mcp/transports/stdio.ts +254 -0
  68. package/src/memory/backends/base.ts +22 -0
  69. package/src/memory/backends/markdown.ts +283 -0
  70. package/src/memory/backends/sqlite.ts +329 -0
  71. package/src/memory/cache.ts +238 -0
  72. package/src/memory/indexer.ts +238 -0
  73. package/src/memory/manager.ts +572 -0
  74. package/src/terminal/adapters/base.ts +29 -0
  75. package/src/terminal/adapters/native.ts +504 -0
  76. package/src/terminal/adapters/vscode.ts +340 -0
  77. package/src/terminal/manager.ts +308 -0
  78. package/src/terminal/pool.ts +271 -0
  79. package/src/terminal/session.ts +250 -0
  80. package/src/terminal/vscode-bridge.ts +242 -0
  81. package/src/utils/errors.ts +231 -0
  82. package/src/utils/helpers.ts +476 -0
  83. package/src/utils/types.ts +493 -0
@@ -0,0 +1,763 @@
1
+ /**
2
+ * Workflow execution commands for Claude-Flow
3
+ */
4
+
5
+ import { Command } from '@cliffy/command';
6
+ import { colors } from '@cliffy/ansi/colors';
7
+ import { Table } from '@cliffy/table';
8
+ import { Confirm, Input } from '@cliffy/prompt';
9
+ import { formatDuration, formatStatusIndicator, formatProgressBar } from '../formatter.ts';
10
+ import { generateId } from '../../utils/helpers.ts';
11
+
12
+ export const workflowCommand = new Command()
13
+ .description('Execute and manage workflows')
14
+ .action(() => {
15
+ workflowCommand.showHelp();
16
+ })
17
+ .command('run', new Command()
18
+ .description('Execute a workflow from file')
19
+ .arguments('<workflow-file:string>')
20
+ .option('-d, --dry-run', 'Validate workflow without executing')
21
+ .option('-v, --variables <vars:string>', 'Override variables (JSON format)')
22
+ .option('-w, --watch', 'Watch workflow execution progress')
23
+ .option('--parallel', 'Allow parallel execution where possible')
24
+ .option('--fail-fast', 'Stop on first task failure')
25
+ .action(async (options: any, workflowFile: string) => {
26
+ await runWorkflow(workflowFile, options);
27
+ }),
28
+ )
29
+ .command('validate', new Command()
30
+ .description('Validate a workflow file')
31
+ .arguments('<workflow-file:string>')
32
+ .option('--strict', 'Use strict validation mode')
33
+ .action(async (options: any, workflowFile: string) => {
34
+ await validateWorkflow(workflowFile, options);
35
+ }),
36
+ )
37
+ .command('list', new Command()
38
+ .description('List running workflows')
39
+ .option('--all', 'Include completed workflows')
40
+ .option('--format <format:string>', 'Output format (table, json)', { default: 'table' })
41
+ .action(async (options: any) => {
42
+ await listWorkflows(options);
43
+ }),
44
+ )
45
+ .command('status', new Command()
46
+ .description('Show workflow execution status')
47
+ .arguments('<workflow-id:string>')
48
+ .option('-w, --watch', 'Watch workflow progress')
49
+ .action(async (options: any, workflowId: string) => {
50
+ await showWorkflowStatus(workflowId, options);
51
+ }),
52
+ )
53
+ .command('stop', new Command()
54
+ .description('Stop a running workflow')
55
+ .arguments('<workflow-id:string>')
56
+ .option('-f, --force', 'Force stop without cleanup')
57
+ .action(async (options: any, workflowId: string) => {
58
+ await stopWorkflow(workflowId, options);
59
+ }),
60
+ )
61
+ .command('template', new Command()
62
+ .description('Generate workflow templates')
63
+ .arguments('<template-type:string>')
64
+ .option('-o, --output <file:string>', 'Output file path')
65
+ .option('--format <format:string>', 'Template format (json, yaml)', { default: 'json' })
66
+ .action(async (options: any, templateType: string) => {
67
+ await generateTemplate(templateType, options);
68
+ }),
69
+ );
70
+
71
+ interface WorkflowDefinition {
72
+ name: string;
73
+ version?: string;
74
+ description?: string;
75
+ variables?: Record<string, any>;
76
+ agents?: AgentDefinition[];
77
+ tasks: TaskDefinition[];
78
+ dependencies?: Record<string, string[]>;
79
+ settings?: WorkflowSettings;
80
+ }
81
+
82
+ interface AgentDefinition {
83
+ id: string;
84
+ type: string;
85
+ name?: string;
86
+ config?: Record<string, any>;
87
+ }
88
+
89
+ interface TaskDefinition {
90
+ id: string;
91
+ name?: string;
92
+ type: string;
93
+ description: string;
94
+ assignTo?: string;
95
+ depends?: string[];
96
+ input?: Record<string, any>;
97
+ timeout?: number;
98
+ retries?: number;
99
+ condition?: string;
100
+ }
101
+
102
+ interface WorkflowSettings {
103
+ maxConcurrency?: number;
104
+ timeout?: number;
105
+ retryPolicy?: 'none' | 'immediate' | 'exponential';
106
+ failurePolicy?: 'fail-fast' | 'continue' | 'ignore';
107
+ }
108
+
109
+ interface WorkflowExecution {
110
+ id: string;
111
+ workflowName: string;
112
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'stopped';
113
+ startedAt: Date;
114
+ completedAt?: Date;
115
+ progress: {
116
+ total: number;
117
+ completed: number;
118
+ failed: number;
119
+ };
120
+ tasks: TaskExecution[];
121
+ }
122
+
123
+ interface TaskExecution {
124
+ id: string;
125
+ taskId: string;
126
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
127
+ startedAt?: Date;
128
+ completedAt?: Date;
129
+ assignedAgent?: string;
130
+ error?: string;
131
+ output?: any;
132
+ }
133
+
134
+ async function runWorkflow(workflowFile: string, options: any): Promise<void> {
135
+ try {
136
+ // Load and validate workflow
137
+ const workflow = await loadWorkflow(workflowFile);
138
+
139
+ if (options.dryRun) {
140
+ await validateWorkflowDefinition(workflow, true);
141
+ console.log(colors.green('✓ Workflow validation passed'));
142
+ return;
143
+ }
144
+
145
+ // Override variables if provided
146
+ if (options.variables) {
147
+ try {
148
+ const vars = JSON.parse(options.variables);
149
+ workflow.variables = { ...workflow.variables, ...vars };
150
+ } catch (error) {
151
+ throw new Error(`Invalid variables JSON: ${(error as Error).message}`);
152
+ }
153
+ }
154
+
155
+ // Create execution plan
156
+ const execution = await createExecution(workflow);
157
+
158
+ console.log(colors.cyan.bold('Starting workflow execution'));
159
+ console.log(`${colors.white('Workflow:')} ${workflow.name}`);
160
+ console.log(`${colors.white('ID:')} ${execution.id}`);
161
+ console.log(`${colors.white('Tasks:')} ${execution.tasks.length}`);
162
+ console.log();
163
+
164
+ // Execute workflow
165
+ if (options.watch) {
166
+ await executeWorkflowWithWatch(execution, workflow, options);
167
+ } else {
168
+ await executeWorkflow(execution, workflow, options);
169
+ }
170
+ } catch (error) {
171
+ console.error(colors.red('Workflow execution failed:'), (error as Error).message);
172
+ Deno.exit(1);
173
+ }
174
+ }
175
+
176
+ async function validateWorkflow(workflowFile: string, options: any): Promise<void> {
177
+ try {
178
+ const workflow = await loadWorkflow(workflowFile);
179
+ await validateWorkflowDefinition(workflow, options.strict);
180
+
181
+ console.log(colors.green('✓ Workflow validation passed'));
182
+ console.log(`${colors.white('Name:')} ${workflow.name}`);
183
+ console.log(`${colors.white('Tasks:')} ${workflow.tasks.length}`);
184
+ console.log(`${colors.white('Agents:')} ${workflow.agents?.length || 0}`);
185
+
186
+ if (workflow.dependencies) {
187
+ const depCount = Object.values(workflow.dependencies).flat().length;
188
+ console.log(`${colors.white('Dependencies:')} ${depCount}`);
189
+ }
190
+ } catch (error) {
191
+ console.error(colors.red('✗ Workflow validation failed:'), (error as Error).message);
192
+ Deno.exit(1);
193
+ }
194
+ }
195
+
196
+ async function listWorkflows(options: any): Promise<void> {
197
+ try {
198
+ // Mock workflow list - in production, this would query the orchestrator
199
+ const workflows = await getRunningWorkflows(options.all);
200
+
201
+ if (options.format === 'json') {
202
+ console.log(JSON.stringify(workflows, null, 2));
203
+ return;
204
+ }
205
+
206
+ if (workflows.length === 0) {
207
+ console.log(colors.gray('No workflows found'));
208
+ return;
209
+ }
210
+
211
+ console.log(colors.cyan.bold(`Workflows (${workflows.length})`));
212
+ console.log('─'.repeat(60));
213
+
214
+ const table = new Table()
215
+ .header(['ID', 'Name', 'Status', 'Progress', 'Started', 'Duration'])
216
+ .border(true);
217
+
218
+ for (const workflow of workflows) {
219
+ const statusIcon = formatStatusIndicator(workflow.status);
220
+ const progress = `${workflow.progress.completed}/${workflow.progress.total}`;
221
+ const progressBar = formatProgressBar(
222
+ workflow.progress.completed,
223
+ workflow.progress.total,
224
+ 10
225
+ );
226
+ const duration = workflow.completedAt
227
+ ? formatDuration(workflow.completedAt.getTime() - workflow.startedAt.getTime())
228
+ : formatDuration(Date.now() - workflow.startedAt.getTime());
229
+
230
+ table.push([
231
+ colors.gray(workflow.id.substring(0, 8) + '...'),
232
+ colors.white(workflow.workflowName),
233
+ `${statusIcon} ${workflow.status}`,
234
+ `${progressBar} ${progress}`,
235
+ workflow.startedAt.toLocaleTimeString(),
236
+ duration
237
+ ]);
238
+ }
239
+
240
+ table.render();
241
+ } catch (error) {
242
+ console.error(colors.red('Failed to list workflows:'), (error as Error).message);
243
+ }
244
+ }
245
+
246
+ async function showWorkflowStatus(workflowId: string, options: any): Promise<void> {
247
+ try {
248
+ if (options.watch) {
249
+ await watchWorkflowStatus(workflowId);
250
+ } else {
251
+ const execution = await getWorkflowExecution(workflowId);
252
+ displayWorkflowStatus(execution);
253
+ }
254
+ } catch (error) {
255
+ console.error(colors.red('Failed to get workflow status:'), (error as Error).message);
256
+ }
257
+ }
258
+
259
+ async function stopWorkflow(workflowId: string, options: any): Promise<void> {
260
+ try {
261
+ const execution = await getWorkflowExecution(workflowId);
262
+
263
+ if (execution.status !== 'running') {
264
+ console.log(colors.yellow(`Workflow is not running (status: ${execution.status})`));
265
+ return;
266
+ }
267
+
268
+ if (!options.force) {
269
+ const confirmed = await Confirm.prompt({
270
+ message: `Stop workflow "${execution.workflowName}"?`,
271
+ default: false,
272
+ });
273
+
274
+ if (!confirmed) {
275
+ console.log(colors.gray('Stop cancelled'));
276
+ return;
277
+ }
278
+ }
279
+
280
+ console.log(colors.yellow('Stopping workflow...'));
281
+
282
+ // Mock stopping - in production, this would call the orchestrator
283
+ if (options.force) {
284
+ console.log(colors.red('• Force stopping all tasks'));
285
+ } else {
286
+ console.log(colors.blue('• Gracefully stopping tasks'));
287
+ console.log(colors.blue('• Cleaning up resources'));
288
+ }
289
+
290
+ console.log(colors.green('✓ Workflow stopped'));
291
+ } catch (error) {
292
+ console.error(colors.red('Failed to stop workflow:'), (error as Error).message);
293
+ }
294
+ }
295
+
296
+ async function generateTemplate(templateType: string, options: any): Promise<void> {
297
+ const templates: Record<string, WorkflowDefinition> = {
298
+ 'research': {
299
+ name: 'Research Workflow',
300
+ description: 'Multi-stage research and analysis workflow',
301
+ variables: {
302
+ 'topic': 'quantum computing',
303
+ 'depth': 'comprehensive'
304
+ },
305
+ agents: [
306
+ { id: 'researcher', type: 'researcher', name: 'Research Agent' },
307
+ { id: 'analyzer', type: 'analyst', name: 'Analysis Agent' }
308
+ ],
309
+ tasks: [
310
+ {
311
+ id: 'research-task',
312
+ type: 'research',
313
+ description: 'Research the given topic',
314
+ assignTo: 'researcher',
315
+ input: { topic: '${topic}', depth: '${depth}' }
316
+ },
317
+ {
318
+ id: 'analyze-task',
319
+ type: 'analysis',
320
+ description: 'Analyze research findings',
321
+ assignTo: 'analyzer',
322
+ depends: ['research-task'],
323
+ input: { data: '${research-task.output}' }
324
+ }
325
+ ],
326
+ settings: {
327
+ maxConcurrency: 2,
328
+ timeout: 300000,
329
+ failurePolicy: 'fail-fast'
330
+ }
331
+ },
332
+ 'implementation': {
333
+ name: 'Implementation Workflow',
334
+ description: 'Code implementation and testing workflow',
335
+ agents: [
336
+ { id: 'implementer', type: 'implementer', name: 'Implementation Agent' },
337
+ { id: 'tester', type: 'implementer', name: 'Testing Agent' }
338
+ ],
339
+ tasks: [
340
+ {
341
+ id: 'implement',
342
+ type: 'implementation',
343
+ description: 'Implement the solution',
344
+ assignTo: 'implementer'
345
+ },
346
+ {
347
+ id: 'test',
348
+ type: 'testing',
349
+ description: 'Test the implementation',
350
+ assignTo: 'tester',
351
+ depends: ['implement']
352
+ }
353
+ ]
354
+ },
355
+ 'coordination': {
356
+ name: 'Multi-Agent Coordination',
357
+ description: 'Complex multi-agent coordination workflow',
358
+ agents: [
359
+ { id: 'coordinator', type: 'coordinator', name: 'Coordinator Agent' },
360
+ { id: 'worker1', type: 'implementer', name: 'Worker Agent 1' },
361
+ { id: 'worker2', type: 'implementer', name: 'Worker Agent 2' }
362
+ ],
363
+ tasks: [
364
+ {
365
+ id: 'plan',
366
+ type: 'planning',
367
+ description: 'Create execution plan',
368
+ assignTo: 'coordinator'
369
+ },
370
+ {
371
+ id: 'work1',
372
+ type: 'implementation',
373
+ description: 'Execute part 1',
374
+ assignTo: 'worker1',
375
+ depends: ['plan']
376
+ },
377
+ {
378
+ id: 'work2',
379
+ type: 'implementation',
380
+ description: 'Execute part 2',
381
+ assignTo: 'worker2',
382
+ depends: ['plan']
383
+ },
384
+ {
385
+ id: 'integrate',
386
+ type: 'integration',
387
+ description: 'Integrate results',
388
+ assignTo: 'coordinator',
389
+ depends: ['work1', 'work2']
390
+ }
391
+ ],
392
+ settings: {
393
+ maxConcurrency: 3,
394
+ failurePolicy: 'continue'
395
+ }
396
+ }
397
+ };
398
+
399
+ const template = templates[templateType];
400
+ if (!template) {
401
+ console.error(colors.red(`Unknown template type: ${templateType}`));
402
+ console.log(colors.gray('Available templates:'), Object.keys(templates).join(', '));
403
+ return;
404
+ }
405
+
406
+ const outputFile = options.output || `${templateType}-workflow.${options.format}`;
407
+
408
+ let content: string;
409
+ if (options.format === 'yaml') {
410
+ // In production, use a proper YAML library
411
+ console.log(colors.yellow('YAML format not implemented, using JSON'));
412
+ content = JSON.stringify(template, null, 2);
413
+ } else {
414
+ content = JSON.stringify(template, null, 2);
415
+ }
416
+
417
+ await Deno.writeTextFile(outputFile, content);
418
+
419
+ console.log(colors.green('✓ Workflow template generated'));
420
+ console.log(`${colors.white('Template:')} ${templateType}`);
421
+ console.log(`${colors.white('File:')} ${outputFile}`);
422
+ console.log(`${colors.white('Tasks:')} ${template.tasks.length}`);
423
+ console.log(`${colors.white('Agents:')} ${template.agents?.length || 0}`);
424
+ }
425
+
426
+ async function loadWorkflow(workflowFile: string): Promise<WorkflowDefinition> {
427
+ try {
428
+ const content = await Deno.readTextFile(workflowFile);
429
+
430
+ if (workflowFile.endsWith('.yaml') || workflowFile.endsWith('.yml')) {
431
+ // In production, use a proper YAML parser
432
+ throw new Error('YAML workflows not yet supported');
433
+ }
434
+
435
+ return JSON.parse(content) as WorkflowDefinition;
436
+ } catch (error) {
437
+ throw new Error(`Failed to load workflow file: ${(error as Error).message}`);
438
+ }
439
+ }
440
+
441
+ async function validateWorkflowDefinition(workflow: WorkflowDefinition, strict = false): Promise<void> {
442
+ const errors: string[] = [];
443
+
444
+ // Basic validation
445
+ if (!workflow.name) errors.push('Workflow name is required');
446
+ if (!workflow.tasks || workflow.tasks.length === 0) errors.push('At least one task is required');
447
+
448
+ // Task validation
449
+ const taskIds = new Set<string>();
450
+ for (const task of workflow.tasks || []) {
451
+ if (!task.id) errors.push('Task ID is required');
452
+ if (taskIds.has(task.id)) errors.push(`Duplicate task ID: ${task.id}`);
453
+ taskIds.add(task.id);
454
+
455
+ if (!task.type) errors.push(`Task ${task.id}: type is required`);
456
+ if (!task.description) errors.push(`Task ${task.id}: description is required`);
457
+
458
+ // Validate dependencies
459
+ if (task.depends) {
460
+ for (const dep of task.depends) {
461
+ if (!taskIds.has(dep)) {
462
+ // Check if dependency exists in previous tasks
463
+ const taskIndex = workflow.tasks.indexOf(task);
464
+ const depExists = workflow.tasks.slice(0, taskIndex).some(t => t.id === dep);
465
+ if (!depExists) {
466
+ errors.push(`Task ${task.id}: unknown dependency ${dep}`);
467
+ }
468
+ }
469
+ }
470
+ }
471
+ }
472
+
473
+ // Agent validation
474
+ if (workflow.agents) {
475
+ const agentIds = new Set<string>();
476
+ for (const agent of workflow.agents) {
477
+ if (!agent.id) errors.push('Agent ID is required');
478
+ if (agentIds.has(agent.id)) errors.push(`Duplicate agent ID: ${agent.id}`);
479
+ agentIds.add(agent.id);
480
+
481
+ if (!agent.type) errors.push(`Agent ${agent.id}: type is required`);
482
+ }
483
+
484
+ // Validate task assignments
485
+ for (const task of workflow.tasks) {
486
+ if (task.assignTo && !agentIds.has(task.assignTo)) {
487
+ errors.push(`Task ${task.id}: assigned to unknown agent ${task.assignTo}`);
488
+ }
489
+ }
490
+ }
491
+
492
+ // Strict validation
493
+ if (strict) {
494
+ // Check for circular dependencies
495
+ const graph = new Map<string, string[]>();
496
+ for (const task of workflow.tasks) {
497
+ graph.set(task.id, task.depends || []);
498
+ }
499
+
500
+ if (hasCircularDependencies(graph)) {
501
+ errors.push('Circular dependencies detected');
502
+ }
503
+ }
504
+
505
+ if (errors.length > 0) {
506
+ throw new Error('Workflow validation failed:\n• ' + errors.join('\n• '));
507
+ }
508
+ }
509
+
510
+ async function createExecution(workflow: WorkflowDefinition): Promise<WorkflowExecution> {
511
+ const tasks: TaskExecution[] = workflow.tasks.map(task => ({
512
+ id: generateId('task-exec'),
513
+ taskId: task.id,
514
+ status: 'pending'
515
+ }));
516
+
517
+ return {
518
+ id: generateId('workflow-exec'),
519
+ workflowName: workflow.name,
520
+ status: 'pending',
521
+ startedAt: new Date(),
522
+ progress: {
523
+ total: tasks.length,
524
+ completed: 0,
525
+ failed: 0
526
+ },
527
+ tasks
528
+ };
529
+ }
530
+
531
+ async function executeWorkflow(execution: WorkflowExecution, workflow: WorkflowDefinition, options: any): Promise<void> {
532
+ execution.status = 'running';
533
+
534
+ console.log(colors.blue('Executing workflow...'));
535
+ console.log();
536
+
537
+ // Mock execution - in production, this would use the orchestrator
538
+ for (let i = 0; i < execution.tasks.length; i++) {
539
+ const taskExec = execution.tasks[i];
540
+ const taskDef = workflow.tasks.find(t => t.id === taskExec.taskId)!;
541
+
542
+ console.log(`${colors.cyan('→')} Starting task: ${taskDef.description}`);
543
+
544
+ taskExec.status = 'running';
545
+ taskExec.startedAt = new Date();
546
+
547
+ // Simulate task execution
548
+ await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));
549
+
550
+ // Random success/failure for demo
551
+ const success = Math.random() > 0.1; // 90% success rate
552
+
553
+ if (success) {
554
+ taskExec.status = 'completed';
555
+ taskExec.completedAt = new Date();
556
+ execution.progress.completed++;
557
+ console.log(`${colors.green('✓')} Completed: ${taskDef.description}`);
558
+ } else {
559
+ taskExec.status = 'failed';
560
+ taskExec.completedAt = new Date();
561
+ taskExec.error = 'Simulated task failure';
562
+ execution.progress.failed++;
563
+ console.log(`${colors.red('✗')} Failed: ${taskDef.description}`);
564
+
565
+ if (options.failFast || workflow.settings?.failurePolicy === 'fail-fast') {
566
+ execution.status = 'failed';
567
+ console.log(colors.red('\nWorkflow failed (fail-fast mode)'));
568
+ return;
569
+ }
570
+ }
571
+
572
+ console.log();
573
+ }
574
+
575
+ execution.status = execution.progress.failed > 0 ? 'failed' : 'completed';
576
+ execution.completedAt = new Date();
577
+
578
+ const duration = formatDuration(execution.completedAt.getTime() - execution.startedAt.getTime());
579
+
580
+ if (execution.status === 'completed') {
581
+ console.log(colors.green.bold('✓ Workflow completed successfully'));
582
+ } else {
583
+ console.log(colors.red.bold('✗ Workflow completed with failures'));
584
+ }
585
+
586
+ console.log(`${colors.white('Duration:')} ${duration}`);
587
+ console.log(`${colors.white('Tasks:')} ${execution.progress.completed}/${execution.progress.total} completed`);
588
+
589
+ if (execution.progress.failed > 0) {
590
+ console.log(`${colors.white('Failed:')} ${execution.progress.failed}`);
591
+ }
592
+ }
593
+
594
+ async function executeWorkflowWithWatch(execution: WorkflowExecution, workflow: WorkflowDefinition, options: any): Promise<void> {
595
+ console.log(colors.yellow('Starting workflow execution in watch mode...'));
596
+ console.log(colors.gray('Press Ctrl+C to stop\n'));
597
+
598
+ // Start execution in background and watch progress
599
+ const executionPromise = executeWorkflow(execution, workflow, options);
600
+
601
+ // Watch loop
602
+ const watchInterval = setInterval(() => {
603
+ displayWorkflowProgress(execution);
604
+ }, 1000);
605
+
606
+ try {
607
+ await executionPromise;
608
+ } finally {
609
+ clearInterval(watchInterval);
610
+ displayWorkflowProgress(execution);
611
+ }
612
+ }
613
+
614
+ async function watchWorkflowStatus(workflowId: string): Promise<void> {
615
+ console.log(colors.cyan('Watching workflow status...'));
616
+ console.log(colors.gray('Press Ctrl+C to stop\n'));
617
+
618
+ // eslint-disable-next-line no-constant-condition
619
+ while (true) {
620
+ try {
621
+ console.clear();
622
+ const execution = await getWorkflowExecution(workflowId);
623
+ displayWorkflowStatus(execution);
624
+
625
+ if (execution.status === 'completed' || execution.status === 'failed' || execution.status === 'stopped') {
626
+ console.log('\n' + colors.gray('Workflow finished. Exiting watch mode.'));
627
+ break;
628
+ }
629
+
630
+ await new Promise(resolve => setTimeout(resolve, 2000));
631
+ } catch (error) {
632
+ console.error(colors.red('Error watching workflow:'), (error as Error).message);
633
+ break;
634
+ }
635
+ }
636
+ }
637
+
638
+ function displayWorkflowStatus(execution: WorkflowExecution): void {
639
+ console.log(colors.cyan.bold('Workflow Status'));
640
+ console.log('─'.repeat(50));
641
+
642
+ const statusIcon = formatStatusIndicator(execution.status);
643
+ const duration = execution.completedAt
644
+ ? formatDuration(execution.completedAt.getTime() - execution.startedAt.getTime())
645
+ : formatDuration(Date.now() - execution.startedAt.getTime());
646
+
647
+ console.log(`${colors.white('Name:')} ${execution.workflowName}`);
648
+ console.log(`${colors.white('ID:')} ${execution.id}`);
649
+ console.log(`${colors.white('Status:')} ${statusIcon} ${execution.status}`);
650
+ console.log(`${colors.white('Started:')} ${execution.startedAt.toLocaleString()}`);
651
+ console.log(`${colors.white('Duration:')} ${duration}`);
652
+
653
+ const progressBar = formatProgressBar(
654
+ execution.progress.completed,
655
+ execution.progress.total,
656
+ 40,
657
+ 'Progress'
658
+ );
659
+ console.log(`${progressBar} ${execution.progress.completed}/${execution.progress.total}`);
660
+
661
+ if (execution.progress.failed > 0) {
662
+ console.log(`${colors.white('Failed Tasks:')} ${colors.red(execution.progress.failed.toString())}`);
663
+ }
664
+ console.log();
665
+
666
+ // Task details
667
+ console.log(colors.cyan.bold('Tasks'));
668
+ console.log('─'.repeat(50));
669
+
670
+ const table = new Table()
671
+ .header(['Task', 'Status', 'Duration', 'Agent'])
672
+ .border(true);
673
+
674
+ for (const taskExec of execution.tasks) {
675
+ const statusIcon = formatStatusIndicator(taskExec.status);
676
+ const duration = taskExec.completedAt && taskExec.startedAt
677
+ ? formatDuration(taskExec.completedAt.getTime() - taskExec.startedAt.getTime())
678
+ : taskExec.startedAt
679
+ ? formatDuration(Date.now() - taskExec.startedAt.getTime())
680
+ : '-';
681
+
682
+ table.push([
683
+ colors.white(taskExec.taskId),
684
+ `${statusIcon} ${taskExec.status}`,
685
+ duration,
686
+ taskExec.assignedAgent || '-'
687
+ ]);
688
+ }
689
+
690
+ table.render();
691
+ }
692
+
693
+ function displayWorkflowProgress(execution: WorkflowExecution): void {
694
+ const progress = `${execution.progress.completed}/${execution.progress.total}`;
695
+ const progressBar = formatProgressBar(
696
+ execution.progress.completed,
697
+ execution.progress.total,
698
+ 30
699
+ );
700
+
701
+ console.log(`\r${progressBar} ${progress} tasks completed`);
702
+ }
703
+
704
+ async function getRunningWorkflows(includeAll = false): Promise<WorkflowExecution[]> {
705
+ // Mock workflow list - in production, this would query the orchestrator
706
+ return [
707
+ {
708
+ id: 'workflow-001',
709
+ workflowName: 'Research Workflow',
710
+ status: 'running' as const,
711
+ startedAt: new Date(Date.now() - 120000), // 2 minutes ago
712
+ progress: { total: 5, completed: 3, failed: 0 },
713
+ tasks: []
714
+ },
715
+ {
716
+ id: 'workflow-002',
717
+ workflowName: 'Implementation Workflow',
718
+ status: 'completed' as const,
719
+ startedAt: new Date(Date.now() - 300000), // 5 minutes ago
720
+ completedAt: new Date(Date.now() - 60000), // 1 minute ago
721
+ progress: { total: 3, completed: 3, failed: 0 },
722
+ tasks: []
723
+ }
724
+ ].filter(w => includeAll || w.status === 'running');
725
+ }
726
+
727
+ async function getWorkflowExecution(workflowId: string): Promise<WorkflowExecution> {
728
+ const workflows = await getRunningWorkflows(true);
729
+ const workflow = workflows.find(w => w.id === workflowId || w.id.startsWith(workflowId));
730
+
731
+ if (!workflow) {
732
+ throw new Error(`Workflow '${workflowId}' not found`);
733
+ }
734
+
735
+ return workflow;
736
+ }
737
+
738
+ function hasCircularDependencies(graph: Map<string, string[]>): boolean {
739
+ const visited = new Set<string>();
740
+ const recursionStack = new Set<string>();
741
+
742
+ function hasCycle(node: string): boolean {
743
+ if (recursionStack.has(node)) return true;
744
+ if (visited.has(node)) return false;
745
+
746
+ visited.add(node);
747
+ recursionStack.add(node);
748
+
749
+ const dependencies = graph.get(node) || [];
750
+ for (const dep of dependencies) {
751
+ if (hasCycle(dep)) return true;
752
+ }
753
+
754
+ recursionStack.delete(node);
755
+ return false;
756
+ }
757
+
758
+ for (const node of graph.keys()) {
759
+ if (hasCycle(node)) return true;
760
+ }
761
+
762
+ return false;
763
+ }