claude-agents-manager
Version:
Elite AI research and development platform with 60+ specialized agents, comprehensive research workflows, citation-backed reports, and advanced multi-agent coordination for Claude Code. Features deep research capabilities, concurrent execution, shared mem
437 lines (377 loc) ⢠11.7 kB
JavaScript
import inquirer from "inquirer";
import chalk from "chalk";
import { getWorkflowManager } from "../utils/workflow.js";
import { getMemoryStore } from "../memory/index.js";
/**
* Workflow management command for orchestrating multiple agents
*/
export async function workflowCommand(options = {}) {
console.log(chalk.blue.bold("\nš Claude Agents Workflow Manager"));
console.log(
chalk.gray("Orchestrate multiple agents for complex enterprise tasks\n"),
);
const workflowManager = getWorkflowManager();
const memory = getMemoryStore();
try {
if (options.list) {
await listWorkflows(workflowManager);
return;
}
if (options.status) {
await showWorkflowStatus(options.status, workflowManager);
return;
}
if (options.template) {
await executeWorkflowTemplate(options.template, workflowManager);
return;
}
// Interactive workflow selection
const action = await promptWorkflowAction();
switch (action) {
case "execute-template":
await executeWorkflowInteractive(workflowManager);
break;
case "create-custom":
await createCustomWorkflow(workflowManager);
break;
case "view-templates":
await viewWorkflowTemplates(workflowManager);
break;
case "workflow-history":
await viewWorkflowHistory(memory);
break;
default:
console.log(chalk.yellow("Operation cancelled"));
}
} catch (error) {
console.error(chalk.red("ā Workflow operation failed:"), error.message);
process.exit(1);
}
}
async function promptWorkflowAction() {
const { action } = await inquirer.prompt([
{
type: "list",
name: "action",
message: "What would you like to do?",
choices: [
{
name: "š Execute Workflow Template - Run pre-built workflow",
value: "execute-template",
},
{
name: "š Create Custom Workflow - Build new workflow",
value: "create-custom",
},
{
name: "š View Workflow Templates - Browse available templates",
value: "view-templates",
},
{
name: "š Workflow History - View past executions",
value: "workflow-history",
},
],
},
]);
return action;
}
async function executeWorkflowInteractive(workflowManager) {
const templates = workflowManager.getAvailableTemplates();
if (templates.length === 0) {
console.log(chalk.yellow("No workflow templates available"));
return;
}
const { selectedTemplate } = await inquirer.prompt([
{
type: "list",
name: "selectedTemplate",
message: "Select workflow template to execute:",
choices: templates.map((template) => ({
name: `${template.name} - ${template.description} (${template.phases} phases)`,
value: template.id,
})),
},
]);
// Get any context needed for the workflow
const context = await promptWorkflowContext(selectedTemplate);
console.log(chalk.blue("\nStarting workflow execution..."));
try {
const workflowId = await workflowManager.executeWorkflow(
selectedTemplate,
context,
);
console.log(chalk.green(`\nā
Workflow completed successfully!`));
console.log(chalk.gray(`Workflow ID: ${workflowId}`));
// Offer to view results
const { viewResults } = await inquirer.prompt([
{
type: "confirm",
name: "viewResults",
message: "Would you like to view detailed results?",
default: true,
},
]);
if (viewResults) {
await showWorkflowStatus(workflowId, workflowManager);
}
} catch (error) {
console.error(
chalk.red(`\nā Workflow execution failed: ${error.message}`),
);
}
}
async function promptWorkflowContext(templateId) {
const context = {};
// Different templates might need different context
switch (templateId) {
case "fullstack-development":
const { projectName, techStack } = await inquirer.prompt([
{
type: "input",
name: "projectName",
message: "Project name:",
default: "my-app",
},
{
type: "checkbox",
name: "techStack",
message: "Select technology stack:",
choices: [
{ name: "React", value: "react" },
{ name: "Node.js", value: "nodejs" },
{ name: "PostgreSQL", value: "postgresql" },
{ name: "TypeScript", value: "typescript" },
{ name: "Docker", value: "docker" },
],
},
]);
context.projectName = projectName;
context.techStack = techStack;
break;
case "data-science-pipeline":
const { dataSource, businessGoal } = await inquirer.prompt([
{
type: "input",
name: "dataSource",
message: "Data source description:",
default: "Customer transaction data",
},
{
type: "input",
name: "businessGoal",
message: "Business objective:",
default: "Predict customer churn",
},
]);
context.dataSource = dataSource;
context.businessGoal = businessGoal;
break;
case "enterprise-consulting":
const { clientName, industry } = await inquirer.prompt([
{
type: "input",
name: "clientName",
message: "Client organization:",
default: "Enterprise Corp",
},
{
type: "list",
name: "industry",
message: "Industry sector:",
choices: [
"Technology",
"Finance",
"Healthcare",
"Manufacturing",
"Retail",
"Other",
],
},
]);
context.clientName = clientName;
context.industry = industry;
break;
}
return context;
}
async function executeWorkflowTemplate(templateId, workflowManager) {
console.log(chalk.blue(`\nExecuting workflow template: ${templateId}`));
try {
const workflowId = await workflowManager.executeWorkflow(templateId, {});
console.log(chalk.green(`\nā
Workflow completed! ID: ${workflowId}`));
} catch (error) {
console.error(chalk.red(`\nā Workflow failed: ${error.message}`));
}
}
async function showWorkflowStatus(workflowId, workflowManager) {
const status = workflowManager.getWorkflowStatus(workflowId);
if (!status) {
console.log(chalk.yellow(`Workflow ${workflowId} not found`));
return;
}
console.log(chalk.blue.bold("\nš Workflow Status"));
console.log(chalk.blue("=".repeat(40)));
console.log(`ID: ${status.id}`);
console.log(`Status: ${getStatusColor(status.status)}`);
console.log(`Duration: ${status.duration}ms`);
console.log(`Phases: ${status.phases.length}`);
if (status.phases.length > 0) {
console.log(chalk.blue("\nPhases:"));
status.phases.forEach((phase, index) => {
console.log(
` ${index + 1}. ${phase.name} - ${getStatusColor(phase.status)}`,
);
});
}
}
function getStatusColor(status) {
switch (status) {
case "completed":
return chalk.green(status);
case "running":
return chalk.yellow(status);
case "failed":
return chalk.red(status);
default:
return chalk.gray(status);
}
}
async function viewWorkflowTemplates(workflowManager) {
const templates = workflowManager.getAvailableTemplates();
console.log(chalk.blue.bold("\nš Available Workflow Templates"));
console.log(chalk.blue("=".repeat(50)));
if (templates.length === 0) {
console.log(chalk.yellow("No workflow templates available"));
return;
}
templates.forEach((template, index) => {
console.log(`\n${index + 1}. ${chalk.bold(template.name)}`);
console.log(` ${chalk.gray(template.description)}`);
console.log(` ${chalk.cyan(`${template.phases} phases`)}`);
});
}
async function createCustomWorkflow(workflowManager) {
console.log(chalk.blue("\nš Create Custom Workflow"));
const { name, description } = await inquirer.prompt([
{
type: "input",
name: "name",
message: "Workflow name:",
validate: (input) => input.length > 0 || "Name is required",
},
{
type: "input",
name: "description",
message: "Workflow description:",
validate: (input) => input.length > 0 || "Description is required",
},
]);
const phases = [];
let addingPhases = true;
while (addingPhases) {
const phase = await createWorkflowPhase(phases.length + 1);
phases.push(phase);
const { addAnother } = await inquirer.prompt([
{
type: "confirm",
name: "addAnother",
message: "Add another phase?",
default: false,
},
]);
addingPhases = addAnother;
}
const templateId = workflowManager.createCustomWorkflow(
name,
description,
phases,
);
console.log(
chalk.green(
`\nā
Custom workflow '${name}' created with ID: ${templateId}`,
),
);
const { executeNow } = await inquirer.prompt([
{
type: "confirm",
name: "executeNow",
message: "Execute the workflow now?",
default: false,
},
]);
if (executeNow) {
await executeWorkflowTemplate(templateId, workflowManager);
}
}
async function createWorkflowPhase(phaseNumber) {
console.log(chalk.cyan(`\nPhase ${phaseNumber} Configuration`));
const { name, parallel } = await inquirer.prompt([
{
type: "input",
name: "name",
message: "Phase name:",
validate: (input) => input.length > 0 || "Phase name is required",
},
{
type: "confirm",
name: "parallel",
message: "Execute agents in parallel?",
default: true,
},
]);
const agents = [];
let addingAgents = true;
while (addingAgents) {
const { agentName, task } = await inquirer.prompt([
{
type: "input",
name: "agentName",
message: "Agent name:",
validate: (input) => input.length > 0 || "Agent name is required",
},
{
type: "input",
name: "task",
message: "Task description:",
validate: (input) => input.length > 0 || "Task description is required",
},
]);
agents.push({ name: agentName, task });
const { addAnother } = await inquirer.prompt([
{
type: "confirm",
name: "addAnother",
message: "Add another agent to this phase?",
default: true,
},
]);
addingAgents = addAnother;
}
return { name, parallel, agents };
}
async function viewWorkflowHistory(memory) {
console.log(chalk.blue.bold("\nš Workflow History"));
console.log(chalk.blue("=".repeat(40)));
// Get workflow summaries from memory
const summaries = memory.getByPattern("workflow:*:summary");
if (Object.keys(summaries).length === 0) {
console.log(chalk.yellow("No workflow history available"));
return;
}
Object.entries(summaries).forEach(([key, summary]) => {
const workflowId = key.split(":")[1];
console.log(`\nš ${summary.name}`);
console.log(` ID: ${workflowId}`);
console.log(` Status: ${getStatusColor(summary.status)}`);
console.log(` Duration: ${summary.duration}ms`);
console.log(` Phases: ${summary.phases}`);
console.log(
` Completed: ${new Date(summary.completedAt).toLocaleString()}`,
);
});
}
async function listWorkflows(workflowManager) {
console.log(chalk.blue.bold("\nš Available Workflows"));
await viewWorkflowTemplates(workflowManager);
}