ready for handover test

This commit is contained in:
ValueOn AG 2025-07-08 01:21:27 +02:00
parent 8d8b800859
commit 55fed49a28
3 changed files with 163 additions and 3 deletions

View file

@ -728,6 +728,10 @@ NOTE: Respond with ONLY the JSON object. Do not include any explanatory text."""
action.setSuccess()
action.result = result.data.get("result", "")
action.execResultLabel = result.data.get("resultLabel", "")
# Create and store message in workflow for successful action
await self._createActionMessage(action, result, workflow)
else:
action.setError(result.error or "Action execution failed")
@ -749,6 +753,143 @@ NOTE: Respond with ONLY the JSON object. Do not include any explanatory text."""
"action": action
}
async def _createActionMessage(self, action: TaskAction, result: Any, workflow: ChatWorkflow) -> None:
"""Create and store a message for the action result in the workflow"""
try:
# Get result data
result_data = result.data if hasattr(result, 'data') else {}
result_label = result_data.get("resultLabel", "")
documents_data = result_data.get("documents", [])
# Create message data
message_data = {
"workflowId": workflow.id,
"role": "assistant",
"message": f"Executed {action.execMethod}.{action.execAction} successfully",
"status": "step",
"sequenceNr": len(workflow.messages) + 1,
"publishedAt": datetime.now(UTC).isoformat(),
"actionId": action.id,
"actionMethod": action.execMethod,
"actionName": action.execAction,
"documentsLabel": result_label, # Use resultLabel as documentsLabel
"documents": []
}
# Process documents if any
if documents_data:
processed_documents = []
for doc_data in documents_data:
try:
# Extract document information
document_name = doc_data.get("documentName", f"{action.execMethod}_{action.execAction}_{datetime.now(UTC).strftime('%Y%m%d_%H%M%S')}")
document_data = doc_data.get("documentData", {})
# Determine file extension and MIME type
file_extension = self._getFileExtension(document_name)
mime_type = self._getMimeType(file_extension)
# Convert document data to string content
content = self._convertDocumentDataToString(document_data, file_extension)
# Create file in database
file_id = self.service.createFile(
fileName=document_name,
mimeType=mime_type,
content=content,
base64encoded=False
)
# Create ChatDocument object
document = self.service.createDocument(
fileName=document_name,
mimeType=mime_type,
content=content,
base64encoded=False
)
if document:
processed_documents.append(document)
logger.info(f"Created document: {document_name} with file ID: {file_id}")
except Exception as e:
logger.error(f"Error processing document {doc_data.get('documentName', 'unknown')}: {str(e)}")
continue
# Update message with processed documents
message_data["documents"] = processed_documents
# Create message using interface
message = self.chatInterface.createWorkflowMessage(message_data)
if message:
workflow.messages.append(message)
logger.info(f"Created action message for {action.execMethod}.{action.execAction} with {len(message_data.get('documents', []))} documents")
else:
logger.error(f"Failed to create workflow message for action {action.execMethod}.{action.execAction}")
except Exception as e:
logger.error(f"Error creating action message: {str(e)}")
def _getFileExtension(self, filename: str) -> str:
"""Extract file extension from filename"""
if '.' in filename:
return filename.split('.')[-1].lower()
return "txt" # Default to text
def _getMimeType(self, extension: str) -> str:
"""Get MIME type based on file extension"""
mime_types = {
'txt': 'text/plain',
'json': 'application/json',
'xml': 'application/xml',
'csv': 'text/csv',
'html': 'text/html',
'md': 'text/markdown',
'py': 'text/x-python',
'js': 'application/javascript',
'css': 'text/css',
'pdf': 'application/pdf',
'doc': 'application/msword',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xls': 'application/vnd.ms-excel',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'ppt': 'application/vnd.ms-powerpoint',
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
}
return mime_types.get(extension, 'application/octet-stream')
def _convertDocumentDataToString(self, document_data: Dict[str, Any], file_extension: str) -> str:
"""Convert document data to string content based on file type"""
try:
if file_extension == 'json':
return json.dumps(document_data, indent=2, ensure_ascii=False)
elif file_extension in ['txt', 'md', 'html', 'css', 'js', 'py']:
# For text files, try to extract text content
if isinstance(document_data, dict):
# Look for common text content fields
text_fields = ['content', 'text', 'data', 'result', 'summary']
for field in text_fields:
if field in document_data:
content = document_data[field]
if isinstance(content, str):
return content
elif isinstance(content, (dict, list)):
return json.dumps(content, indent=2, ensure_ascii=False)
# If no text field found, convert entire dict to JSON
return json.dumps(document_data, indent=2, ensure_ascii=False)
elif isinstance(document_data, str):
return document_data
else:
return str(document_data)
else:
# For other file types, convert to JSON
return json.dumps(document_data, indent=2, ensure_ascii=False)
except Exception as e:
logger.error(f"Error converting document data to string: {str(e)}")
return str(document_data)
async def _performTaskReview(self, review_context: Dict[str, Any]) -> Dict[str, Any]:
"""Perform AI-based task review"""
try:
@ -778,11 +919,23 @@ NOTE: Respond with ONLY the JSON object. Do not include any explanatory text."""
}
def _getPreviousResultsFromActions(self, task_actions: List[TaskAction]) -> List[str]:
"""Get list of previous results from completed actions"""
"""Get list of previous results from completed actions and workflow messages"""
results = []
# Get results from action objects
for action in task_actions:
if action.execResultLabel and action.isSuccessful():
results.append(action.execResultLabel)
# Get results from workflow messages (for actions that have been executed)
if hasattr(self, 'workflow') and self.workflow and self.workflow.messages:
for message in self.workflow.messages:
if (message.role == 'assistant' and
message.status == 'step' and
message.documentsLabel and
message.documentsLabel not in results):
results.append(message.documentsLabel)
return results
def _calculateTaskQualityMetrics(self, task_step: Dict[str, Any], action_results: List[Dict[str, Any]]) -> Dict[str, Any]:

View file

@ -224,7 +224,7 @@ class ServiceContainer:
if message.documentsLabel.startswith("mdoc:"):
return message.documentsLabel
# Otherwise construct the reference
# Otherwise construct the reference using the action ID and documents label
return f"mdoc:{message.actionId}:{message.documentsLabel}"
def getChatDocumentsFromDocumentReference(self, documentReference: str) -> List[ChatDocument]:
@ -256,6 +256,14 @@ class ServiceContainer:
message.documentsLabel == documentReference and # Compare full reference
message.documents):
return message.documents
# If not found by actionId, try to find by documentsLabel only
# This handles cases where the reference format might be different
for message in self.workflow.messages:
if (message.documentsLabel and
message.documentsLabel == documentReference and
message.documents):
return message.documents
return []

View file

@ -34,7 +34,6 @@ LOGIC
TODO methods:
- reultLabel not to generate in the function, but to be set according to the action definition
- align documentList objects: chat document to have prefix "cdoc", message document list to have prefix "mdoc" (globally: instead of document and documentList)
- after action execution to store the documents in db and in a message object