permamind
Version:
An MCP server that provides an immortal memory layer for AI agents and clients
972 lines (971 loc) • 38.6 kB
JavaScript
// Workflow template library
const WORKFLOW_TEMPLATES = {
"software-development": {
category: "development",
description: "Complete software development workflow from requirements to deployment",
id: "software-development",
name: "Software Development Lifecycle",
presets: [
{
description: "Configuration for small projects",
name: "Small Project",
tags: ["small", "quick"],
variables: { complexity: "simple", teamSize: 3 },
},
{
description: "Configuration for large enterprise projects",
name: "Enterprise Project",
tags: ["enterprise", "large"],
variables: { complexity: "complex", teamSize: 15 },
},
],
template: {
agentAssignments: [],
dependencies: [],
description: "Standard software development workflow",
id: "software-dev-template",
metadata: {
author: "BMAD System",
category: "development",
complexity: "moderate",
createdAt: new Date().toISOString(),
estimatedDuration: 3360, // 56 hours total
status: "active",
tags: ["software", "development", "lifecycle"],
updatedAt: new Date().toISOString(),
version: "1.0.0",
},
name: "Software Development",
stages: [
{
assignedAgents: ["analyst", "pm"],
deliverables: ["requirements-document"],
description: "Gather and analyze requirements",
estimatedDuration: 480, // 8 hours
exitCriteria: ["requirements-approved"],
id: "requirements",
name: "Requirements Analysis",
order: 1,
parallelExecution: false,
prerequisites: [],
tasks: [],
},
{
assignedAgents: ["architect", "ux-expert"],
deliverables: ["architecture-document", "ui-mockups"],
description: "Create system architecture and design",
estimatedDuration: 720, // 12 hours
exitCriteria: ["design-approved"],
id: "design",
name: "System Design",
order: 2,
parallelExecution: false,
prerequisites: ["requirements"],
tasks: [],
},
{
assignedAgents: ["developer"],
deliverables: ["source-code", "unit-tests"],
description: "Implement the designed solution",
estimatedDuration: 1440, // 24 hours
exitCriteria: ["code-review-passed", "tests-passing"],
id: "implementation",
name: "Code Implementation",
order: 3,
parallelExecution: true,
prerequisites: ["design"],
tasks: [],
},
{
assignedAgents: ["qa"],
deliverables: ["test-results", "bug-reports"],
description: "Test the implemented solution",
estimatedDuration: 480, // 8 hours
exitCriteria: ["qa-approved"],
id: "testing",
name: "Quality Assurance",
order: 4,
parallelExecution: false,
prerequisites: ["implementation"],
tasks: [],
},
{
assignedAgents: ["developer", "pm"],
deliverables: ["deployment-package", "deployment-logs"],
description: "Deploy the solution to production",
estimatedDuration: 240, // 4 hours
exitCriteria: ["deployment-successful"],
id: "deployment",
name: "Deployment",
order: 5,
parallelExecution: false,
prerequisites: ["testing"],
tasks: [],
},
],
triggers: [],
version: "1.0.0",
},
variables: [
{
description: "Name of the project",
name: "projectName",
required: true,
type: "string",
},
{
defaultValue: 5,
description: "Number of team members",
name: "teamSize",
required: false,
type: "number",
},
{
defaultValue: "moderate",
description: "Project complexity level",
name: "complexity",
required: false,
type: "string",
},
],
},
};
export class WorkflowAutomationServiceImpl {
teamAgentService;
processService;
memoryService;
constructor(teamAgentService, processService, memoryService) {
this.teamAgentService = teamAgentService;
this.processService = processService;
this.memoryService = memoryService;
}
async cancelWorkflowExecution(executionId, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
if (!execution) {
return false;
}
execution.status = "cancelled";
execution.completedAt = new Date().toISOString();
await this.storeWorkflowExecution(execution, {}, hubId);
return true;
}
catch (error) {
return false;
}
}
async createWorkflow(workflowDef, signer, hubId) {
try {
// Validate workflow definition
this.validateWorkflowDefinition(workflowDef);
// Store workflow in memory service
const workflowMemory = {
content: JSON.stringify(workflowDef),
context: {
domain: "workflow_definition",
sessionId: `workflow_${workflowDef.id}`,
topic: workflowDef.name,
},
importance: 0.9,
memoryType: "workflow",
};
await this.memoryService.addEnhanced(signer, hubId, workflowMemory);
return workflowDef.id;
}
catch (error) {
throw new Error(`Failed to create workflow: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async createWorkflowTemplate(template, hubId) {
try {
const templateMemory = {
content: JSON.stringify(template),
context: {
domain: "workflow_template",
topic: template.name,
},
importance: 0.8,
memoryType: "workflow",
};
await this.memoryService.addEnhanced({}, hubId, templateMemory);
return template.id;
}
catch (error) {
throw new Error(`Failed to create workflow template: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async deleteWorkflow(workflowId, hubId) {
try {
const workflow = await this.getWorkflow(workflowId, hubId);
if (!workflow) {
return false;
}
// Mark workflow as archived
return await this.updateWorkflow(workflowId, { metadata: { ...workflow.metadata, status: "archived" } }, hubId);
}
catch (error) {
return false;
}
}
async executeWorkflow(workflowId, context, signer, hubId) {
const startTime = new Date().toISOString();
const executionId = `exec_${workflowId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
try {
const workflow = await this.getWorkflow(workflowId, hubId);
if (!workflow) {
return {
error: {
code: "WORKFLOW_NOT_FOUND",
message: `Workflow ${workflowId} not found`,
retryable: false,
},
executionId,
startedAt: startTime,
status: "failed",
success: false,
};
}
// Create workflow execution record
const execution = {
context,
currentStage: workflow.stages[0]?.id,
id: executionId,
participants: [],
progress: {
completedStages: 0,
completedTasks: 0,
estimatedTimeRemaining: workflow.metadata.estimatedDuration,
overallPercent: 0,
totalStages: workflow.stages.length,
totalTasks: workflow.stages.reduce((total, stage) => total + stage.tasks.length, 0),
},
results: [],
startedAt: startTime,
status: "running",
workflowId,
};
// Store execution record
await this.storeWorkflowExecution(execution, signer, hubId);
// Execute workflow stages
const results = await this.executeWorkflowStages(workflow, execution, signer, hubId);
// Update execution status
execution.status = results.length > 0 ? "completed" : "failed";
execution.completedAt = new Date().toISOString();
execution.results = results;
await this.storeWorkflowExecution(execution, signer, hubId);
return {
executionId,
results,
startedAt: startTime,
status: execution.status,
success: execution.status === "completed",
};
}
catch (error) {
return {
error: {
code: "EXECUTION_FAILED",
message: error instanceof Error ? error.message : "Unknown error",
retryable: true,
},
executionId,
startedAt: startTime,
status: "failed",
success: false,
};
}
}
async executeWorkflowOnAO(workflowId, processId, parameters, signer, hubId) {
const startTime = Date.now();
try {
// Get workflow and integration configuration
const workflow = await this.getWorkflow(workflowId, hubId);
if (!workflow) {
return {
duration: Date.now() - startTime,
error: {
code: "WORKFLOW_NOT_FOUND",
message: "Workflow not found",
retryable: false,
},
processId,
success: false,
};
}
// Execute workflow through process communication service
const processResult = await this.processService.executeProcessRequest(JSON.stringify(workflow), processId, `Execute workflow: ${workflow.name}`, signer);
return {
duration: Date.now() - startTime,
error: processResult.success !== false
? undefined
: {
code: "AO_EXECUTION_FAILED",
message: processResult.error || "AO execution failed",
retryable: true,
},
processId,
result: processResult.data,
success: processResult.success !== false,
};
}
catch (error) {
return {
duration: Date.now() - startTime,
error: {
code: "EXECUTION_ERROR",
message: error instanceof Error ? error.message : "Unknown error",
retryable: true,
},
processId,
success: false,
};
}
}
async executeWorkflowRequest(naturalLanguageRequest, workflowId, signer, hubId) {
try {
const workflow = await this.getWorkflow(workflowId, hubId);
if (!workflow) {
return {
error: `Workflow ${workflowId} not found`,
estimatedDuration: 0,
interpretation: "Workflow not found",
parameters: {},
requiredApprovals: [],
success: false,
};
}
// Parse natural language request
const interpretation = this.interpretWorkflowRequest(naturalLanguageRequest);
const parameters = this.extractParametersFromRequest(naturalLanguageRequest);
const estimatedDuration = this.estimateRequestDuration(naturalLanguageRequest, workflow);
// Execute the workflow
const executionContext = {
constraints: [],
environment: "development",
parameters,
resources: [],
triggeredBy: "natural_language_request",
};
const result = await this.executeWorkflow(workflowId, executionContext, signer, hubId);
return {
error: result.error?.message,
estimatedDuration,
executionId: result.executionId,
interpretation,
parameters,
requiredApprovals: [], // Would be determined based on workflow requirements
success: result.success,
};
}
catch (error) {
return {
error: error instanceof Error ? error.message : "Unknown error",
estimatedDuration: 0,
interpretation: "Failed to process request",
parameters: {},
requiredApprovals: [],
success: false,
};
}
}
async generateWorkflowReport(executionId, reportType, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
if (!execution) {
throw new Error("Execution not found");
}
const workflow = await this.getWorkflow(execution.workflowId, hubId);
if (!workflow) {
throw new Error("Workflow not found");
}
const reportId = `report_${executionId}_${Date.now()}`;
const content = await this.generateReportContent(execution, workflow, reportType);
return {
content,
executionId,
generatedAt: new Date().toISOString(),
reportId,
reportType,
workflowId: execution.workflowId,
};
}
catch (error) {
throw new Error(`Failed to generate workflow report: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async getWorkflow(workflowId, hubId) {
try {
const memories = await this.memoryService.searchAdvanced(hubId, `workflow_${workflowId}`, { memoryType: "workflow" });
if (memories.length === 0) {
return null;
}
return JSON.parse(memories[0].content);
}
catch (error) {
throw new Error(`Failed to get workflow: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async getWorkflowAnalytics(workflowId, hubId) {
try {
// Get all executions for this workflow
const executions = await this.getWorkflowExecutions(workflowId, hubId);
const analytics = {
averageDuration: this.calculateAverageDuration(executions),
errorPatterns: this.analyzeErrorPatterns(executions),
executionTrends: this.calculateExecutionTrends(executions),
performanceInsights: this.generatePerformanceInsights(executions),
popularStages: this.calculateStageUsage(executions),
successRate: executions.filter((e) => e.status === "completed").length /
executions.length,
totalExecutions: executions.length,
workflowId,
};
return analytics;
}
catch (error) {
throw new Error(`Failed to get workflow analytics: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async getWorkflowExecution(executionId, hubId) {
try {
const memories = await this.memoryService.searchAdvanced(hubId, `execution_${executionId}`, { memoryType: "workflow" });
if (memories.length === 0) {
return null;
}
return JSON.parse(memories[0].content);
}
catch (error) {
return null;
}
}
async getWorkflowProgress(executionId, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
return execution?.progress || null;
}
catch (error) {
return null;
}
}
async getWorkflowResults(executionId, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
return execution?.results || [];
}
catch (error) {
return [];
}
}
async instantiateFromTemplate(templateId, variables, hubId) {
try {
// Check built-in templates first
const builtInTemplate = WORKFLOW_TEMPLATES[templateId];
let template;
if (builtInTemplate) {
template = builtInTemplate;
}
else {
// Search for custom templates
const memories = await this.memoryService.searchAdvanced(hubId, `template_${templateId}`, { memoryType: "workflow" });
if (memories.length === 0) {
throw new Error(`Template ${templateId} not found`);
}
template = JSON.parse(memories[0].content);
}
// Instantiate workflow from template
const workflow = { ...template.template };
workflow.id = `${templateId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
workflow.metadata.createdAt = new Date().toISOString();
workflow.metadata.updatedAt = new Date().toISOString();
// Apply variable substitution
this.applyVariableSubstitution(workflow, template.variables, variables);
return workflow;
}
catch (error) {
throw new Error(`Failed to instantiate from template: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async integrateWithAOProcesses(workflowId, processConfig, hubId) {
try {
const workflow = await this.getWorkflow(workflowId, hubId);
if (!workflow) {
return {
error: "Workflow not found",
integrationId: "",
mappings: processConfig,
success: false,
validatedHandlers: [],
};
}
// Validate AO process handlers
const validatedHandlers = [];
for (const [stageId, handler] of Object.entries(processConfig.handlerMapping)) {
try {
// Validate that stage exists in workflow
const stage = workflow.stages.find((s) => s.id === stageId);
if (stage) {
validatedHandlers.push(handler);
}
}
catch (error) {
// Skip invalid handlers
}
}
const integrationId = `integration_${workflowId}_${Date.now()}`;
// Store integration configuration
const integrationMemory = {
content: JSON.stringify({
processConfig,
validatedHandlers,
workflowId,
}),
context: {
domain: "ao_integration",
sessionId: integrationId,
topic: `workflow_${workflowId}_ao`,
},
importance: 0.8,
memoryType: "workflow",
};
await this.memoryService.addEnhanced({}, hubId, integrationMemory);
return {
integrationId,
mappings: processConfig,
success: true,
validatedHandlers,
};
}
catch (error) {
return {
error: error instanceof Error ? error.message : "Unknown error",
integrationId: "",
mappings: processConfig,
success: false,
validatedHandlers: [],
};
}
}
async listWorkflows(hubId, category) {
try {
const searchQuery = category
? `workflow_definition category:${category}`
: "workflow_definition";
const memories = await this.memoryService.searchAdvanced(hubId, searchQuery, { memoryType: "workflow" });
const workflows = [];
for (const memory of memories) {
try {
const workflowData = JSON.parse(memory.content);
if (workflowData.stages &&
(!category || workflowData.metadata.category === category)) {
workflows.push(workflowData);
}
}
catch (parseError) {
continue;
}
}
return workflows.sort((a, b) => a.metadata.updatedAt.localeCompare(b.metadata.updatedAt));
}
catch (error) {
throw new Error(`Failed to list workflows: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async listWorkflowTemplates(hubId) {
try {
// Include built-in templates
const builtInTemplates = Object.values(WORKFLOW_TEMPLATES);
// Get custom templates
const memories = await this.memoryService.searchAdvanced(hubId, "workflow_template", { memoryType: "workflow" });
const customTemplates = [];
for (const memory of memories) {
try {
const template = JSON.parse(memory.content);
if (template.template && template.variables) {
customTemplates.push(template);
}
}
catch (parseError) {
continue;
}
}
return [...builtInTemplates, ...customTemplates];
}
catch (error) {
throw new Error(`Failed to list workflow templates: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async parseNaturalLanguageWorkflow(description, context) {
try {
// Simple natural language parsing implementation
// In a real implementation, this would use more sophisticated NLP
const workflowId = `nl_workflow_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
// Extract workflow components from description
const stages = this.extractStagesFromDescription(description);
const estimatedDuration = this.estimateDurationFromDescription(description);
const workflow = {
agentAssignments: [],
dependencies: [],
description,
id: workflowId,
metadata: {
author: "Natural Language Parser",
category: "custom",
complexity: "moderate",
createdAt: new Date().toISOString(),
estimatedDuration,
status: "draft",
tags: ["natural-language", "auto-generated"],
updatedAt: new Date().toISOString(),
version: "1.0.0",
},
name: `Natural Language Workflow: ${description.substring(0, 50)}...`,
stages,
triggers: [],
version: "1.0.0",
};
return workflow;
}
catch (error) {
throw new Error(`Failed to parse natural language workflow: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
async pauseWorkflowExecution(executionId, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
if (!execution || execution.status !== "running") {
return false;
}
execution.status = "paused";
await this.storeWorkflowExecution(execution, {}, hubId);
return true;
}
catch (error) {
return false;
}
}
async resumeWorkflowExecution(executionId, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
if (!execution || execution.status !== "paused") {
return false;
}
execution.status = "running";
await this.storeWorkflowExecution(execution, {}, hubId);
return true;
}
catch (error) {
return false;
}
}
async updateWorkflow(workflowId, updates, hubId) {
try {
const workflow = await this.getWorkflow(workflowId, hubId);
if (!workflow) {
return false;
}
const updatedWorkflow = { ...workflow, ...updates };
updatedWorkflow.metadata.updatedAt = new Date().toISOString();
// Store updated workflow
const workflowMemory = {
content: JSON.stringify(updatedWorkflow),
context: {
domain: "workflow_definition",
sessionId: `workflow_${workflowId}`,
topic: updatedWorkflow.name,
},
importance: 0.9,
memoryType: "workflow",
};
await this.memoryService.addEnhanced({}, hubId, workflowMemory);
return true;
}
catch (error) {
return false;
}
}
async updateWorkflowState(executionId, state, hubId) {
try {
const execution = await this.getWorkflowExecution(executionId, hubId);
if (!execution) {
return false;
}
if (state.currentStage)
execution.currentStage = state.currentStage;
if (state.status)
execution.status = state.status;
if (state.progress)
execution.progress = { ...execution.progress, ...state.progress };
if (state.results)
execution.results.push(...state.results);
await this.storeWorkflowExecution(execution, {}, hubId);
return true;
}
catch (error) {
return false;
}
}
analyzeErrorPatterns(executions) {
// Analyze common error patterns
return [];
}
applyVariableSubstitution(workflow, templateVars, values) {
// Apply variable substitution to workflow definition
// This would replace template variables with actual values
}
calculateAverageDuration(executions) {
const completedExecutions = executions.filter((e) => e.completedAt);
if (completedExecutions.length === 0)
return 0;
const totalDuration = completedExecutions.reduce((sum, e) => {
const duration = new Date(e.completedAt).getTime() - new Date(e.startedAt).getTime();
return sum + duration;
}, 0);
return totalDuration / completedExecutions.length;
}
calculateExecutionTrends(executions) {
// Group executions by date and calculate trends
const trends = {};
executions.forEach((execution) => {
const date = execution.startedAt.split("T")[0];
if (!trends[date]) {
trends[date] = {
averageDuration: 0,
date,
executions: 0,
successRate: 0,
};
}
trends[date].executions++;
});
return Object.values(trends);
}
calculateStageUsage(executions) {
// Calculate stage usage statistics
return [];
}
estimateDurationFromDescription(description) {
// Extract duration estimates from description
const hourMatches = description.match(/(\d+)\s+hours?/gi);
const dayMatches = description.match(/(\d+)\s+days?/gi);
let totalMinutes = 0;
if (hourMatches) {
hourMatches.forEach((match) => {
const hours = parseInt(match.match(/\d+/)?.[0] || "0");
totalMinutes += hours * 60;
});
}
if (dayMatches) {
dayMatches.forEach((match) => {
const days = parseInt(match.match(/\d+/)?.[0] || "0");
totalMinutes += days * 8 * 60; // 8 hours per day
});
}
return totalMinutes || 480; // Default 8 hours
}
estimateRequestDuration(request, workflow) {
// Estimate duration for the request
return workflow.metadata.estimatedDuration;
}
async executeWorkflowStage(stage, execution, signer, hubId) {
// Simulate stage execution
// In a real implementation, this would coordinate with assigned agents
const stageResult = {
approved: true,
notes: `Stage ${stage.name} completed successfully`,
output: {
deliverables: stage.deliverables,
duration: stage.estimatedDuration,
exitCriteria: stage.exitCriteria,
},
quality: 0.9,
stageId: stage.id,
timestamp: new Date().toISOString(),
};
return stageResult;
}
async executeWorkflowStages(workflow, execution, signer, hubId) {
const results = [];
for (const stage of workflow.stages.sort((a, b) => a.order - b.order)) {
try {
// Update current stage
execution.currentStage = stage.id;
await this.storeWorkflowExecution(execution, signer, hubId);
// Execute stage
const stageResult = await this.executeWorkflowStage(stage, execution, signer, hubId);
results.push(stageResult);
// Update progress
execution.progress.completedStages++;
execution.progress.overallPercent =
(execution.progress.completedStages /
execution.progress.totalStages) *
100;
await this.storeWorkflowExecution(execution, signer, hubId);
}
catch (error) {
// Handle stage execution error
const errorResult = {
approved: false,
notes: `Stage execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
output: {
error: error instanceof Error ? error.message : "Unknown error",
},
quality: 0,
stageId: stage.id,
timestamp: new Date().toISOString(),
};
results.push(errorResult);
break; // Stop execution on error
}
}
return results;
}
extractParametersFromRequest(request) {
// Extract parameters from natural language request
return {};
}
extractStagesFromDescription(description) {
// Extract workflow stages from natural language description
// This is a simplified implementation
const stages = [];
// Look for numbered steps or bullet points
const stepMatches = description.match(/\d+\.\s+([^.]+)/g) || [];
stepMatches.forEach((match, index) => {
const stageName = match.replace(/\d+\.\s+/, "").trim();
stages.push({
assignedAgents: [],
deliverables: [],
description: stageName,
estimatedDuration: 60, // 1 hour default
exitCriteria: [],
id: `stage_${index + 1}`,
name: stageName,
order: index + 1,
parallelExecution: false,
prerequisites: index > 0 ? [`stage_${index}`] : [],
tasks: [],
});
});
return stages;
}
generatePerformanceInsights(executions) {
// Generate performance insights
return [];
}
generateRecommendations(execution, workflow) {
const recommendations = [];
if (execution.status !== "completed") {
recommendations.push("Consider reviewing workflow prerequisites and dependencies");
}
if (execution.progress.overallPercent < 50) {
recommendations.push("Workflow progress is below 50% - review stage definitions");
}
return recommendations;
}
async generateReportContent(execution, workflow, reportType) {
// Generate report content based on type
const summary = {
outputsGenerated: execution.results.length,
participantCount: execution.participants.length,
stagesCompleted: execution.progress.completedStages,
successRate: execution.status === "completed" ? 1 : 0,
tasksCompleted: execution.progress.completedTasks,
totalDuration: execution.completedAt
? new Date(execution.completedAt).getTime() -
new Date(execution.startedAt).getTime()
: 0,
};
const stages = workflow.stages.map((stage) => ({
duration: stage.estimatedDuration,
issues: [],
outputs: stage.deliverables,
stageId: stage.id,
stageName: stage.name,
status: execution.results.find((r) => r.stageId === stage.id)
? "completed"
: "in_progress",
tasksCompleted: stage.tasks.length,
tasksTotal: stage.tasks.length,
}));
const performance = {
averageStageTime: workflow.metadata.estimatedDuration / workflow.stages.length,
bottlenecks: [],
efficiency: summary.successRate,
resourceUtilization: {},
throughput: execution.results.length / (summary.totalDuration / 1000 / 60 / 60), // per hour
};
const errors = execution.results
.filter((r) => !r.approved)
.map((r) => ({
errorId: `error_${r.stageId}`,
errorType: "execution",
impact: "medium",
message: r.notes || "Stage execution failed",
stage: r.stageId,
timestamp: r.timestamp,
}));
return {
errors,
performance,
recommendations: this.generateRecommendations(execution, workflow),
stages,
summary,
};
}
async getWorkflowExecutions(workflowId, hubId) {
try {
const memories = await this.memoryService.searchAdvanced(hubId, `workflow_execution ${workflowId}`, { memoryType: "workflow" });
const executions = [];
for (const memory of memories) {
try {
const execution = JSON.parse(memory.content);
if (execution.workflowId === workflowId) {
executions.push(execution);
}
}
catch (parseError) {
continue;
}
}
return executions;
}
catch (error) {
return [];
}
}
interpretWorkflowRequest(request) {
// Interpret natural language request
return `Interpreted request: ${request}`;
}
async storeWorkflowExecution(execution, signer, hubId) {
const executionMemory = {
content: JSON.stringify(execution),
context: {
domain: "workflow_execution",
sessionId: execution.id,
topic: `execution_${execution.id}`,
},
importance: 0.9,
memoryType: "workflow",
};
await this.memoryService.addEnhanced(signer, hubId, executionMemory);
}
// Private helper methods
validateWorkflowDefinition(workflow) {
if (!workflow.id || !workflow.name || !workflow.stages) {
throw new Error("Workflow must have id, name, and stages");
}
if (workflow.stages.length === 0) {
throw new Error("Workflow must have at least one stage");
}
// Validate stage order
const orders = workflow.stages.map((s) => s.order);
const uniqueOrders = new Set(orders);
if (uniqueOrders.size !== orders.length) {
throw new Error("Stage orders must be unique");
}
}
}
// Export singleton service factory
export const createWorkflowAutomationService = (teamAgentService, processService, memoryService) => {
return new WorkflowAutomationServiceImpl(teamAgentService, processService, memoryService);
};