fixed workflow run with chatlog
This commit is contained in:
parent
b205a2c5ad
commit
a958defd42
4 changed files with 87 additions and 36 deletions
|
|
@ -437,19 +437,26 @@ class StructureFiller:
|
||||||
if isinstance(jsonContent, dict) and jsonContent.get("type") == "image":
|
if isinstance(jsonContent, dict) and jsonContent.get("type") == "image":
|
||||||
elements.append(jsonContent)
|
elements.append(jsonContent)
|
||||||
logger.debug("AI returned proper JSON image structure")
|
logger.debug("AI returned proper JSON image structure")
|
||||||
continue
|
# Skip remaining image processing, but continue with progress updates
|
||||||
|
base64Data = None # Signal that image was already processed
|
||||||
elif isinstance(jsonContent, list) and len(jsonContent) > 0:
|
elif isinstance(jsonContent, list) and len(jsonContent) > 0:
|
||||||
# Check if first element is an image
|
# Check if first element is an image
|
||||||
if isinstance(jsonContent[0], dict) and jsonContent[0].get("type") == "image":
|
if isinstance(jsonContent[0], dict) and jsonContent[0].get("type") == "image":
|
||||||
elements.extend(jsonContent)
|
elements.extend(jsonContent)
|
||||||
logger.debug("AI returned proper JSON image structure in list")
|
logger.debug("AI returned proper JSON image structure in list")
|
||||||
continue
|
# Skip remaining image processing, but continue with progress updates
|
||||||
|
base64Data = None # Signal that image was already processed
|
||||||
|
else:
|
||||||
|
base64Data = "" # Continue with normal processing
|
||||||
except (json.JSONDecodeError, ValueError, AttributeError):
|
except (json.JSONDecodeError, ValueError, AttributeError):
|
||||||
# Not JSON, treat as base64 string or data URI
|
# Not JSON, treat as base64 string or data URI
|
||||||
pass
|
base64Data = "" # Will be processed below
|
||||||
|
|
||||||
# Already base64 string or data URI
|
# Process base64 if not already handled above
|
||||||
if aiResponse.content.startswith("data:image/"):
|
if base64Data is None:
|
||||||
|
# Already processed as JSON, skip base64 processing
|
||||||
|
pass
|
||||||
|
elif aiResponse.content.startswith("data:image/"):
|
||||||
# Extract base64 from data URI
|
# Extract base64 from data URI
|
||||||
base64Data = aiResponse.content.split(",", 1)[1]
|
base64Data = aiResponse.content.split(",", 1)[1]
|
||||||
else:
|
else:
|
||||||
|
|
@ -463,8 +470,11 @@ class StructureFiller:
|
||||||
else:
|
else:
|
||||||
base64Data = ""
|
base64Data = ""
|
||||||
|
|
||||||
# Always create proper JSON structure for images
|
# Always create proper JSON structure for images (if not already processed)
|
||||||
if base64Data:
|
if base64Data is None:
|
||||||
|
# Image already processed as JSON, skip
|
||||||
|
pass
|
||||||
|
elif base64Data:
|
||||||
elements.append({
|
elements.append({
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"content": {
|
"content": {
|
||||||
|
|
@ -527,20 +537,20 @@ class StructureFiller:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Fehlerhafte Section mit Fehlermeldung rendern (kein Abbruch!)
|
# Fehlerhafte Section mit Fehlermeldung rendern (kein Abbruch!)
|
||||||
self.services.chat.progressLogFinish(sectionOperationId, False)
|
self.services.chat.progressLogFinish(sectionOperationId, False)
|
||||||
elements.append({
|
elements.append({
|
||||||
"type": "error",
|
"type": "error",
|
||||||
"message": f"Error generating section {sectionId}: {str(e)}",
|
"message": f"Error generating section {sectionId}: {str(e)}",
|
||||||
"sectionId": sectionId
|
"sectionId": sectionId
|
||||||
})
|
})
|
||||||
logger.error(f"Error generating section {sectionId}: {str(e)}")
|
logger.error(f"Error generating section {sectionId}: {str(e)}")
|
||||||
# Still update chapter progress even on error
|
# Still update chapter progress even on error
|
||||||
chapterProgress = (sectionIndex + 1) / totalSections if totalSections > 0 else 1.0
|
chapterProgress = (sectionIndex + 1) / totalSections if totalSections > 0 else 1.0
|
||||||
self.services.chat.progressLogUpdate(
|
self.services.chat.progressLogUpdate(
|
||||||
chapterOperationId,
|
chapterOperationId,
|
||||||
chapterProgress,
|
chapterProgress,
|
||||||
f"Section {sectionIndex + 1}/{totalSections} completed (with errors)"
|
f"Section {sectionIndex + 1}/{totalSections} completed (with errors)"
|
||||||
)
|
)
|
||||||
# NICHT raise - Section wird mit Fehlermeldung gerendert
|
# NICHT raise - Section wird mit Fehlermeldung gerendert
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Einzelverarbeitung: Jeder Part einzeln ODER Generation ohne ContentParts
|
# Einzelverarbeitung: Jeder Part einzeln ODER Generation ohne ContentParts
|
||||||
|
|
@ -634,17 +644,25 @@ class StructureFiller:
|
||||||
if isinstance(jsonContent, dict) and jsonContent.get("type") == "image":
|
if isinstance(jsonContent, dict) and jsonContent.get("type") == "image":
|
||||||
elements.append(jsonContent)
|
elements.append(jsonContent)
|
||||||
logger.debug("AI returned proper JSON image structure")
|
logger.debug("AI returned proper JSON image structure")
|
||||||
continue
|
# Skip remaining image processing, but continue with progress updates
|
||||||
|
base64Data = None # Signal that image was already processed
|
||||||
elif isinstance(jsonContent, list) and len(jsonContent) > 0:
|
elif isinstance(jsonContent, list) and len(jsonContent) > 0:
|
||||||
if isinstance(jsonContent[0], dict) and jsonContent[0].get("type") == "image":
|
if isinstance(jsonContent[0], dict) and jsonContent[0].get("type") == "image":
|
||||||
elements.extend(jsonContent)
|
elements.extend(jsonContent)
|
||||||
logger.debug("AI returned proper JSON image structure in list")
|
logger.debug("AI returned proper JSON image structure in list")
|
||||||
continue
|
# Skip remaining image processing, but continue with progress updates
|
||||||
|
base64Data = None # Signal that image was already processed
|
||||||
|
else:
|
||||||
|
base64Data = "" # Continue with normal processing
|
||||||
except (json.JSONDecodeError, ValueError, AttributeError):
|
except (json.JSONDecodeError, ValueError, AttributeError):
|
||||||
pass
|
base64Data = "" # Will be processed below
|
||||||
|
|
||||||
# Already base64 string or data URI
|
# Process base64 if not already handled above
|
||||||
if aiResponse.content.startswith("data:image/"):
|
if base64Data is None:
|
||||||
|
# Already processed as JSON, skip base64 processing
|
||||||
|
pass
|
||||||
|
elif aiResponse.content.startswith("data:image/"):
|
||||||
|
# Extract base64 from data URI
|
||||||
base64Data = aiResponse.content.split(",", 1)[1]
|
base64Data = aiResponse.content.split(",", 1)[1]
|
||||||
else:
|
else:
|
||||||
content_stripped = aiResponse.content.strip()
|
content_stripped = aiResponse.content.strip()
|
||||||
|
|
@ -655,8 +673,11 @@ class StructureFiller:
|
||||||
else:
|
else:
|
||||||
base64Data = ""
|
base64Data = ""
|
||||||
|
|
||||||
# Always create proper JSON structure for images
|
# Always create proper JSON structure for images (if not already processed)
|
||||||
if base64Data:
|
if base64Data is None:
|
||||||
|
# Image already processed as JSON, skip
|
||||||
|
pass
|
||||||
|
elif base64Data:
|
||||||
elements.append({
|
elements.append({
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"content": {
|
"content": {
|
||||||
|
|
@ -853,17 +874,25 @@ class StructureFiller:
|
||||||
if isinstance(jsonContent, dict) and jsonContent.get("type") == "image":
|
if isinstance(jsonContent, dict) and jsonContent.get("type") == "image":
|
||||||
elements.append(jsonContent)
|
elements.append(jsonContent)
|
||||||
logger.debug("AI returned proper JSON image structure")
|
logger.debug("AI returned proper JSON image structure")
|
||||||
continue
|
# Skip remaining image processing, but continue with progress updates
|
||||||
|
base64Data = None # Signal that image was already processed
|
||||||
elif isinstance(jsonContent, list) and len(jsonContent) > 0:
|
elif isinstance(jsonContent, list) and len(jsonContent) > 0:
|
||||||
if isinstance(jsonContent[0], dict) and jsonContent[0].get("type") == "image":
|
if isinstance(jsonContent[0], dict) and jsonContent[0].get("type") == "image":
|
||||||
elements.extend(jsonContent)
|
elements.extend(jsonContent)
|
||||||
logger.debug("AI returned proper JSON image structure in list")
|
logger.debug("AI returned proper JSON image structure in list")
|
||||||
continue
|
# Skip remaining image processing, but continue with progress updates
|
||||||
|
base64Data = None # Signal that image was already processed
|
||||||
|
else:
|
||||||
|
base64Data = "" # Continue with normal processing
|
||||||
except (json.JSONDecodeError, ValueError, AttributeError):
|
except (json.JSONDecodeError, ValueError, AttributeError):
|
||||||
pass
|
base64Data = "" # Will be processed below
|
||||||
|
|
||||||
# Already base64 string or data URI
|
# Process base64 if not already handled above
|
||||||
if aiResponse.content.startswith("data:image/"):
|
if base64Data is None:
|
||||||
|
# Already processed as JSON, skip base64 processing
|
||||||
|
pass
|
||||||
|
elif aiResponse.content.startswith("data:image/"):
|
||||||
|
# Extract base64 from data URI
|
||||||
base64Data = aiResponse.content.split(",", 1)[1]
|
base64Data = aiResponse.content.split(",", 1)[1]
|
||||||
else:
|
else:
|
||||||
content_stripped = aiResponse.content.strip()
|
content_stripped = aiResponse.content.strip()
|
||||||
|
|
@ -874,8 +903,11 @@ class StructureFiller:
|
||||||
else:
|
else:
|
||||||
base64Data = ""
|
base64Data = ""
|
||||||
|
|
||||||
# Always create proper JSON structure for images
|
# Always create proper JSON structure for images (if not already processed)
|
||||||
if base64Data:
|
if base64Data is None:
|
||||||
|
# Image already processed as JSON, skip
|
||||||
|
pass
|
||||||
|
elif base64Data:
|
||||||
elements.append({
|
elements.append({
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"content": {
|
"content": {
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,10 @@ class ProgressLogger:
|
||||||
logger.warning(f"Cannot log progress: no workflow available")
|
logger.warning(f"Cannot log progress: no workflow available")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Validate parentOperationId exists in activeOperations (for debugging)
|
||||||
|
if parentOperationId and parentOperationId not in self.activeOperations:
|
||||||
|
logger.debug(f"WARNING: Parent operation '{parentOperationId}' not found in activeOperations when creating log for '{operationId}'. Available operations: {list(self.activeOperations.keys())}. Child operation may appear at root level.")
|
||||||
|
|
||||||
# parentId in ChatLog should be the operationId of the parent operation, not the log entry ID
|
# parentId in ChatLog should be the operationId of the parent operation, not the log entry ID
|
||||||
logData = {
|
logData = {
|
||||||
"workflowId": workflow.id,
|
"workflowId": workflow.id,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,11 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
|
|
||||||
# Start progress tracking
|
# Start progress tracking
|
||||||
parentOperationId = parameters.get('parentOperationId')
|
parentOperationId = parameters.get('parentOperationId')
|
||||||
|
if not parentOperationId:
|
||||||
|
logger.warning(f"ai.process: No parentOperationId provided in parameters. Operation '{operationId}' will appear at root level. Available parameters: {list(parameters.keys())}")
|
||||||
|
else:
|
||||||
|
logger.debug(f"ai.process: Using parentOperationId '{parentOperationId}' for operation '{operationId}'")
|
||||||
|
|
||||||
self.services.chat.progressLogStart(
|
self.services.chat.progressLogStart(
|
||||||
operationId,
|
operationId,
|
||||||
"Generate",
|
"Generate",
|
||||||
|
|
|
||||||
|
|
@ -188,9 +188,19 @@ class MethodBase:
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def _validateParameters(self, parameters: Dict[str, Any], paramDefs: Dict[str, WorkflowActionParameter]) -> Dict[str, Any]:
|
def _validateParameters(self, parameters: Dict[str, Any], paramDefs: Dict[str, WorkflowActionParameter]) -> Dict[str, Any]:
|
||||||
"""Validate parameters against definitions"""
|
"""Validate parameters against definitions
|
||||||
|
|
||||||
|
IMPORTANT: System parameters (like parentOperationId, expectedDocumentFormats) are preserved
|
||||||
|
even if they're not in the parameter definitions, as they're used internally by the framework.
|
||||||
|
"""
|
||||||
validated = {}
|
validated = {}
|
||||||
|
|
||||||
|
# System parameters that should always be preserved, even if not in paramDefs
|
||||||
|
systemParams = ['parentOperationId', 'expectedDocumentFormats']
|
||||||
|
for sysParam in systemParams:
|
||||||
|
if sysParam in parameters:
|
||||||
|
validated[sysParam] = parameters[sysParam]
|
||||||
|
|
||||||
for paramName, paramDef in paramDefs.items():
|
for paramName, paramDef in paramDefs.items():
|
||||||
value = parameters.get(paramName)
|
value = parameters.get(paramName)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue