ready for handover test
This commit is contained in:
parent
8d8b800859
commit
55fed49a28
3 changed files with 163 additions and 3 deletions
|
|
@ -728,6 +728,10 @@ NOTE: Respond with ONLY the JSON object. Do not include any explanatory text."""
|
||||||
action.setSuccess()
|
action.setSuccess()
|
||||||
action.result = result.data.get("result", "")
|
action.result = result.data.get("result", "")
|
||||||
action.execResultLabel = result.data.get("resultLabel", "")
|
action.execResultLabel = result.data.get("resultLabel", "")
|
||||||
|
|
||||||
|
# Create and store message in workflow for successful action
|
||||||
|
await self._createActionMessage(action, result, workflow)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
action.setError(result.error or "Action execution failed")
|
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
|
"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]:
|
async def _performTaskReview(self, review_context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""Perform AI-based task review"""
|
"""Perform AI-based task review"""
|
||||||
try:
|
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]:
|
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 = []
|
results = []
|
||||||
|
|
||||||
|
# Get results from action objects
|
||||||
for action in task_actions:
|
for action in task_actions:
|
||||||
if action.execResultLabel and action.isSuccessful():
|
if action.execResultLabel and action.isSuccessful():
|
||||||
results.append(action.execResultLabel)
|
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
|
return results
|
||||||
|
|
||||||
def _calculateTaskQualityMetrics(self, task_step: Dict[str, Any], action_results: List[Dict[str, Any]]) -> Dict[str, Any]:
|
def _calculateTaskQualityMetrics(self, task_step: Dict[str, Any], action_results: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,7 @@ class ServiceContainer:
|
||||||
if message.documentsLabel.startswith("mdoc:"):
|
if message.documentsLabel.startswith("mdoc:"):
|
||||||
return message.documentsLabel
|
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}"
|
return f"mdoc:{message.actionId}:{message.documentsLabel}"
|
||||||
|
|
||||||
def getChatDocumentsFromDocumentReference(self, documentReference: str) -> List[ChatDocument]:
|
def getChatDocumentsFromDocumentReference(self, documentReference: str) -> List[ChatDocument]:
|
||||||
|
|
@ -256,6 +256,14 @@ class ServiceContainer:
|
||||||
message.documentsLabel == documentReference and # Compare full reference
|
message.documentsLabel == documentReference and # Compare full reference
|
||||||
message.documents):
|
message.documents):
|
||||||
return 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 []
|
return []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ LOGIC
|
||||||
|
|
||||||
TODO methods:
|
TODO methods:
|
||||||
- reultLabel not to generate in the function, but to be set according to the action definition
|
- 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
|
- after action execution to store the documents in db and in a message object
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue