gateway/modules/workflow/managerWorkflow.py
2025-06-10 18:19:33 +02:00

147 lines
No EOL
5.7 KiB
Python

from typing import Dict, Any
import logging
from datetime import datetime, UTC
import uuid
from modules.interfaces.serviceChatModel import (
AgentTask, AgentResult, TaskStatus, ChatMessage,
UserInputRequest, ChatWorkflow, ChatDocument
)
from modules.interfaces.serviceChatClass import ChatInterface
from modules.workflow.managerChat import ChatManager
logger = logging.getLogger(__name__)
class WorkflowStoppedException(Exception):
"""Exception raised when workflow is stopped by user"""
pass
class WorkflowManager:
"""Manages workflow execution lifecycle"""
def __init__(self, chatInterface: ChatInterface):
self.workflow = None
self.isRunning = False
self.chatInterface = chatInterface
self.chatManager = ChatManager()
def _checkWorkflowStopped(self, workflow: ChatWorkflow) -> None:
if workflow.status == "stopped":
logger.info(f"Workflow {workflow.id} stopped by user")
raise WorkflowStoppedException("User stopped workflow")
async def workflowProcess(self, userInput: UserInputRequest, workflow: ChatWorkflow) -> None:
"""Main workflow execution process"""
try:
self.workflow = workflow
self.isRunning = True
# Process documents from userInput using ChatInterface's method
documents = []
if userInput.listFileId:
documents = await self.chatInterface.processFileIds(userInput.listFileId)
# Create initial ChatMessage from userInput
initialMessage = ChatMessage(
id=str(uuid.uuid4()),
workflowId=workflow.id,
role="user",
message=userInput.prompt,
status="first", # First message in workflow
documents=documents
)
# Add message to workflow
await self.chatInterface.createWorkflowMessage(initialMessage.dict())
# Create initial task
task = await self.chatInterface.createInitialTask(workflow, initialMessage)
if not task:
logger.error("Failed to create initial task")
workflow.status = "error"
workflow.error = "Failed to create initial task"
return
# Main workflow loop
while self.isRunning and workflow.status == "running":
self._checkWorkflowStopped(workflow)
# Execute task
result = AgentResult(
id=task.id,
status=TaskStatus.PENDING,
createdAt=datetime.now(UTC),
updatedAt=datetime.now(UTC)
)
# Execute each action
for action in task.actionList:
self._checkWorkflowStopped(workflow)
try:
# Execute action
actionResult = await action.execute()
# Update action status
action.status = TaskStatus.COMPLETED if actionResult.success else TaskStatus.FAILED
action.result = actionResult
# Check for failure
if not actionResult.success:
result.status = TaskStatus.FAILED
result.error = actionResult.error
break
except Exception as e:
logger.error(f"Action error: {str(e)}")
action.status = TaskStatus.FAILED
result.status = TaskStatus.FAILED
result.error = str(e)
break
# Update result status
if result.status != TaskStatus.FAILED:
result.status = TaskStatus.COMPLETED
result.updatedAt = datetime.now(UTC)
self._checkWorkflowStopped(workflow)
# Update workflow with result
await self.chatInterface.addTaskResult(workflow, result)
# Get next task
task = await self.chatInterface.getNextTask(workflow)
if not task:
break
# Check if should continue
if not await self.chatInterface.shouldContinue(workflow):
break
# Generate final feedback message using ChatManager
finalFeedback = await self.chatManager.generateWorkflowFeedback(workflow)
# Create final message with "last" status
self._checkWorkflowStopped(workflow)
finalMessage = ChatMessage(
id=str(uuid.uuid4()),
workflowId=workflow.id,
role="assistant",
message=finalFeedback,
status="last" # Last message in workflow
)
await self.chatInterface.createWorkflowMessage(finalMessage.dict())
# Complete workflow
if workflow.status != "failed":
workflow.status = "completed"
workflow.lastActivity = datetime.now(UTC).isoformat()
except Exception as e:
logger.error(f"Workflow error: {str(e)}")
if self.workflow:
self.workflow.status = "error"
self.workflow.error = str(e)