From 2672266eca032b6c96c12f0ccdd9d676c493c84f Mon Sep 17 00:00:00 2001
From: Ida Dittrich <i.dittrich@valueon.ch>
Date: Mon, 5 Jan 2026 06:40:09 +0100
Subject: [PATCH] Merge remote-tracking branch 'origin/int' into dev-ida

:

sage

"messeage"

t
exit
close
git commit
-m "message"
git add .
exit


---
 .../methods/methodAi/actions/process.py       | 141 ++++++++++++------
 1 file changed, 98 insertions(+), 43 deletions(-)

diff --git a/modules/workflows/methods/methodAi/actions/process.py b/modules/workflows/methods/methodAi/actions/process.py
index 0dd37ce3..c76ce35e 100644
--- a/modules/workflows/methods/methodAi/actions/process.py
+++ b/modules/workflows/methods/methodAi/actions/process.py
@@ -54,8 +54,9 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
             logger.error(f"Invalid documentList type: {type(documentListParam)}")
             documentList = DocumentReferenceList(references=[])
         
-        # Optional: if omitted, formats determined from prompt. Default "txt" is validation fallback only.
-        resultType = parameters.get("resultType")
+        resultType = parameters.get("resultType", "txt")
+        simpleMode = parameters.get("simpleMode", False)
+        
         
         if not aiPrompt:
             logger.error(f"aiPrompt is missing or empty. Parameters: {parameters}")
@@ -63,18 +64,11 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
                 error="AI prompt is required"
             )
         
-        # Handle optional resultType: if None, formats determined from prompt by AI
-        if resultType:
-            normalized_result_type = (str(resultType).strip().lstrip('.').lower() or "txt")
-            output_extension = f".{normalized_result_type}"
-            output_format = output_extension.replace('.', '') or 'txt'
-            logger.info(f"Using result type: {resultType} -> {output_extension}")
-        else:
-            # No format specified - AI will determine formats from prompt
-            normalized_result_type = None
-            output_extension = None
-            output_format = None
-            logger.debug("resultType not provided - formats will be determined from prompt by AI")
+        # Determine output extension and default MIME type without duplicating service logic
+        normalized_result_type = (str(resultType).strip().lstrip('.').lower() or "txt")
+        output_extension = f".{normalized_result_type}"
+        output_mime_type = "application/octet-stream"  # Prefer service-provided mimeType when available
+        logger.info(f"Using result type: {resultType} -> {output_extension}, simpleMode: {simpleMode}")
         
         output_mime_type = "application/octet-stream"  # Prefer service-provided mimeType when available
         
@@ -96,38 +90,99 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
         # Update progress - preparing AI call
         self.services.chat.progressLogUpdate(operationId, 0.4, "Preparing AI call")
         
-        # Detect image generation from resultType (if provided)
-        imageFormats = ["png", "jpg", "jpeg", "gif", "webp"]
-        isImageGeneration = normalized_result_type in imageFormats if normalized_result_type else False
+        # Build options
+        output_format = output_extension.replace('.', '') or 'txt'
         
-        # Build options with correct operationType
-        from modules.datamodels.datamodelAi import OperationTypeEnum
-        # resultFormat in options can be None - formats will be determined by AI if not provided
-        options = AiCallOptions(
-            resultFormat=output_format,  # Can be None - formats determined by AI
-            operationType=OperationTypeEnum.IMAGE_GENERATE if isImageGeneration else OperationTypeEnum.DATA_GENERATE
-        )
-        
-        # Get generationIntent from parameters (required for DATA_GENERATE)
-        # Default to "document" if not provided (most common use case)
-        # For code generation, use ai.generateCode action or explicitly pass generationIntent="code"
-        generationIntent = parameters.get("generationIntent", "document")
+        # Simple mode: fast path without document generation pipeline
+        if simpleMode:
+            # Update progress - calling AI (simple mode)
+            self.services.chat.progressLogUpdate(operationId, 0.6, "Calling AI (simple mode)")
+            
+            # Extract context from documents if provided
+            context_text = ""
+            if documentList and len(documentList.references) > 0:
+                try:
+                    # Get documents from workflow
+                    documents = self.services.chat.getChatDocumentsFromDocumentList(documentList)
+                    context_parts = []
+                    for doc in documents:
+                        if hasattr(doc, 'fileId') and doc.fileId:
+                            # Get file data
+                            fileData = self.services.interfaceDbComponent.getFileData(doc.fileId)
+                            if fileData:
+                                if isinstance(fileData, bytes):
+                                    doc_text = fileData.decode('utf-8', errors='ignore')
+                                else:
+                                    doc_text = str(fileData)
+                                context_parts.append(doc_text)
+                    if context_parts:
+                        context_text = "\n\n".join(context_parts)
+                except Exception as e:
+                    logger.warning(f"Error extracting context from documents in simple mode: {e}")
+            
+            # Use direct AI call without document generation pipeline
+            from modules.datamodels.datamodelAi import AiCallRequest, OperationTypeEnum, ProcessingModeEnum
+            request = AiCallRequest(
+                prompt=aiPrompt,
+                context=context_text if context_text else None,
+                options=AiCallOptions(
+                    resultFormat=output_format,
+                    operationType=OperationTypeEnum.DATA_ANALYSE,
+                    processingMode=ProcessingModeEnum.BASIC
+                )
+            )
+            
+            aiResponse_obj = await self.services.ai.callAi(request)
+            
+            # Convert AiCallResponse to AiResponse format
+            from modules.datamodels.datamodelWorkflow import AiResponse, AiResponseMetadata
+            aiResponse = AiResponse(
+                content=aiResponse_obj.content,
+                metadata=AiResponseMetadata(
+                    additionalData={
+                        "modelName": aiResponse_obj.modelName,
+                        "priceUsd": aiResponse_obj.priceUsd,
+                        "processingTime": aiResponse_obj.processingTime,
+                        "bytesSent": aiResponse_obj.bytesSent,
+                        "bytesReceived": aiResponse_obj.bytesReceived,
+                        "errorCount": aiResponse_obj.errorCount
+                    }
+                ),
+                documents=[]  # Simple mode doesn't generate documents
+            )
+        else:
+            # Full mode: use unified callAiContent method
+            options = AiCallOptions(
+                resultFormat=output_format
+            )
 
-        # Update progress - calling AI
-        self.services.chat.progressLogUpdate(operationId, 0.6, "Calling AI")
+            # Update progress - calling AI
+            self.services.chat.progressLogUpdate(operationId, 0.6, "Calling AI")
 
-        # Use unified callAiContent method with BOTH documentList and contentParts
-        # Extraction is handled by AI service - no extraction here
-        # outputFormat: Optional - if None, formats determined from prompt by AI
-        aiResponse = await self.services.ai.callAiContent(
-            prompt=aiPrompt,
-            options=options,
-            documentList=documentList,  # Pass documentList - AI service handles extraction
-            contentParts=contentParts,  # Pass contentParts if provided (or None)
-            outputFormat=output_format,  # Can be None - AI determines from prompt
-            parentOperationId=operationId,
-            generationIntent=generationIntent  # REQUIRED for DATA_GENERATE
-        )
+            # Use unified callAiContent method
+            # If contentParts provided (pre-extracted), use them directly
+            # Otherwise, pass documentList and let callAiContent handle Phases 5A-5E internally
+            # Note: ContentExtracted documents (from context.extractContent) are now handled
+            # automatically in _extractAndPrepareContent() (Phase 5B)
+            if contentParts:
+                # Pre-extracted ContentParts - use them directly
+                aiResponse = await self.services.ai.callAiContent(
+                    prompt=aiPrompt,
+                    options=options,
+                    contentParts=contentParts,  # Pre-extracted ContentParts
+                    outputFormat=output_format,
+                    parentOperationId=operationId
+                )
+            else:
+                # Pass documentList - callAiContent handles Phases 5A-5E internally
+                # This includes automatic detection of ContentExtracted documents
+                aiResponse = await self.services.ai.callAiContent(
+                    prompt=aiPrompt,
+                    options=options,
+                    documentList=documentList,  # callAiContent macht Phasen 5A-5E
+                    outputFormat=output_format,
+                    parentOperationId=operationId
+                )
         
         # Update progress - processing result
         self.services.chat.progressLogUpdate(operationId, 0.8, "Processing result")
