enhanced voice center
This commit is contained in:
parent
9f46ca3b03
commit
6d393f9cf3
8 changed files with 425 additions and 24 deletions
|
|
@ -403,6 +403,61 @@ class ConnectorGoogleSpeech:
|
|||
"error": str(e)
|
||||
}
|
||||
|
||||
async def detectLanguage(self, text: str) -> Dict:
|
||||
"""
|
||||
Detect the language of text using Google Cloud Translation API.
|
||||
|
||||
Args:
|
||||
text: Text to detect language for
|
||||
|
||||
Returns:
|
||||
Dict containing detected language code and confidence
|
||||
"""
|
||||
try:
|
||||
if not text.strip():
|
||||
logger.warning("⚠️ Empty text provided for language detection")
|
||||
return {
|
||||
"success": False,
|
||||
"language": "",
|
||||
"error": "Empty text provided"
|
||||
}
|
||||
|
||||
# Use a sample of the text (middle 1000 bytes or full text if smaller)
|
||||
textBytes = text.encode('utf-8')
|
||||
if len(textBytes) > 1000:
|
||||
# Take 1000 bytes from the middle
|
||||
startPos = (len(textBytes) - 1000) // 2
|
||||
textSample = textBytes[startPos:startPos + 1000].decode('utf-8', errors='ignore')
|
||||
else:
|
||||
textSample = text
|
||||
|
||||
logger.info(f"🔍 Detecting language for text sample: '{textSample[:100]}...'")
|
||||
|
||||
# Use translation API with auto-detection (source_language=None)
|
||||
result = self.translate_client.translate(
|
||||
textSample,
|
||||
source_language=None, # Auto-detect
|
||||
target_language='en' # Dummy target, we only need detection
|
||||
)
|
||||
|
||||
detectedLanguage = result.get('detectedSourceLanguage', '')
|
||||
|
||||
logger.info(f"✅ Language detected: {detectedLanguage}")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"language": detectedLanguage,
|
||||
"confidence": 1.0 # Google Translation API doesn't provide confidence, assume high
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Google Cloud Language Detection error: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"language": "",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def speechToTranslatedText(self, audioContent: bytes,
|
||||
fromLanguage: str = "de-DE",
|
||||
toLanguage: str = "en") -> Dict:
|
||||
|
|
|
|||
|
|
@ -99,6 +99,44 @@ class VoiceObjects:
|
|||
|
||||
# Translation Operations
|
||||
|
||||
async def detectLanguage(self, text: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Detect the language of text using Google Cloud Translation API.
|
||||
|
||||
Args:
|
||||
text: Text to detect language for
|
||||
|
||||
Returns:
|
||||
Dict containing detected language code and confidence
|
||||
"""
|
||||
try:
|
||||
logger.info(f"🔍 Language detection request: '{text[:100]}...'")
|
||||
|
||||
if not text.strip():
|
||||
return {
|
||||
"success": False,
|
||||
"language": "",
|
||||
"error": "Empty text provided"
|
||||
}
|
||||
|
||||
connector = self._getGoogleSpeechConnector()
|
||||
result = await connector.detectLanguage(text)
|
||||
|
||||
if result["success"]:
|
||||
logger.info(f"✅ Language detected: {result['language']}")
|
||||
else:
|
||||
logger.warning(f"⚠️ Language detection failed: {result.get('error', 'Unknown error')}")
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Language detection error: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"language": "",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def translateText(self, text: str, sourceLanguage: str = "de",
|
||||
targetLanguage: str = "en") -> Dict[str, Any]:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -115,6 +115,48 @@ async def speech_to_text(
|
|||
detail=f"Speech-to-text processing failed: {str(e)}"
|
||||
)
|
||||
|
||||
@router.post("/detect-language")
|
||||
async def detect_language(
|
||||
text: str = Form(...),
|
||||
currentUser: User = Depends(getCurrentUser)
|
||||
):
|
||||
"""Detect the language of text using Google Cloud Translation API."""
|
||||
try:
|
||||
logger.info(f"🔍 Language detection request: '{text[:100]}...'")
|
||||
|
||||
if not text.strip():
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Empty text provided for language detection"
|
||||
)
|
||||
|
||||
# Get voice interface
|
||||
voiceInterface = _getVoiceInterface(currentUser)
|
||||
|
||||
# Perform language detection
|
||||
result = await voiceInterface.detectLanguage(text)
|
||||
|
||||
if result["success"]:
|
||||
return {
|
||||
"success": True,
|
||||
"language": result["language"],
|
||||
"confidence": result.get("confidence", 1.0)
|
||||
}
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Language detection failed: {result.get('error', 'Unknown error')}"
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Language detection error: {e}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"Language detection processing failed: {str(e)}"
|
||||
)
|
||||
|
||||
@router.post("/translate")
|
||||
async def translate_text(
|
||||
text: str = Form(...),
|
||||
|
|
|
|||
|
|
@ -172,11 +172,19 @@ class MethodAi(MethodBase):
|
|||
if aiResponse.documents and len(aiResponse.documents) > 0:
|
||||
action_documents = []
|
||||
for doc in aiResponse.documents:
|
||||
validationMetadata = {
|
||||
"actionType": "ai.process",
|
||||
"resultType": normalized_result_type,
|
||||
"outputFormat": output_format,
|
||||
"hasDocuments": True,
|
||||
"documentCount": len(aiResponse.documents)
|
||||
}
|
||||
action_documents.append(ActionDocument(
|
||||
documentName=doc.documentName,
|
||||
documentData=doc.documentData,
|
||||
mimeType=doc.mimeType or output_mime_type,
|
||||
sourceJson=getattr(doc, 'sourceJson', None) # Preserve source JSON for structure validation
|
||||
sourceJson=getattr(doc, 'sourceJson', None), # Preserve source JSON for structure validation
|
||||
validationMetadata=validationMetadata
|
||||
))
|
||||
|
||||
final_documents = action_documents
|
||||
|
|
@ -188,10 +196,18 @@ class MethodAi(MethodBase):
|
|||
extension=extension,
|
||||
action_name="result"
|
||||
)
|
||||
validationMetadata = {
|
||||
"actionType": "ai.process",
|
||||
"resultType": normalized_result_type,
|
||||
"outputFormat": output_format,
|
||||
"hasDocuments": False,
|
||||
"contentType": "text"
|
||||
}
|
||||
action_document = ActionDocument(
|
||||
documentName=meaningful_name,
|
||||
documentData=aiResponse.content,
|
||||
mimeType=output_mime_type
|
||||
mimeType=output_mime_type,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
final_documents = [action_document]
|
||||
|
||||
|
|
@ -288,10 +304,20 @@ class MethodAi(MethodBase):
|
|||
)
|
||||
|
||||
from modules.datamodels.datamodelChat import ActionDocument
|
||||
validationMetadata = {
|
||||
"actionType": "ai.webResearch",
|
||||
"prompt": prompt,
|
||||
"urlList": parameters.get("urlList", []),
|
||||
"country": parameters.get("country"),
|
||||
"language": parameters.get("language"),
|
||||
"researchDepth": parameters.get("researchDepth", "general"),
|
||||
"resultFormat": "json"
|
||||
}
|
||||
actionDocument = ActionDocument(
|
||||
documentName=meaningfulName,
|
||||
documentData=result,
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
|
||||
return ActionResult.isSuccess(documents=[actionDocument])
|
||||
|
|
@ -490,11 +516,19 @@ class MethodAi(MethodBase):
|
|||
rendered_content = self._applyCsvOptions(rendered_content, renderOptions)
|
||||
|
||||
from modules.datamodels.datamodelChat import ActionDocument
|
||||
validationMetadata = {
|
||||
"actionType": "ai.convert",
|
||||
"inputFormat": normalizedInputFormat,
|
||||
"outputFormat": normalizedOutputFormat,
|
||||
"hasSourceJson": True,
|
||||
"conversionType": "direct_rendering"
|
||||
}
|
||||
actionDoc = ActionDocument(
|
||||
documentName=f"{doc.documentName.rsplit('.', 1)[0] if '.' in doc.documentName else doc.documentName}.{normalizedOutputFormat}",
|
||||
documentData=rendered_content,
|
||||
mimeType=mime_type,
|
||||
sourceJson=jsonData # Preserve source JSON for structure validation
|
||||
sourceJson=jsonData, # Preserve source JSON for structure validation
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
|
||||
return ActionResult.isSuccess(documents=[actionDoc])
|
||||
|
|
|
|||
|
|
@ -18,6 +18,19 @@ def action(func):
|
|||
- success: bool
|
||||
- documents: List[ActionDocument]
|
||||
- error: str (if success=False)
|
||||
|
||||
REQUIRED: All ActionDocument instances MUST include validationMetadata for content validation
|
||||
and refinement. Without validationMetadata, results cannot be approved.
|
||||
|
||||
Example validationMetadata structure:
|
||||
validationMetadata = {
|
||||
"actionType": "moduleName.actionName",
|
||||
"param1": value1,
|
||||
"param2": value2,
|
||||
# ... other relevant parameters for validation
|
||||
}
|
||||
|
||||
See MethodBase._createValidationMetadata() for a helper method to create standard metadata.
|
||||
"""
|
||||
@wraps(func)
|
||||
async def wrapper(self, parameters: Dict[str, Any], *args, **kwargs):
|
||||
|
|
@ -26,7 +39,14 @@ def action(func):
|
|||
return wrapper
|
||||
|
||||
class MethodBase:
|
||||
"""Base class for all methods"""
|
||||
"""Base class for all methods
|
||||
|
||||
IMPORTANT: All actions that return ActionDocument instances MUST include validationMetadata.
|
||||
This metadata is required for content validation and refinement. Without it, results cannot
|
||||
be approved by the validation system.
|
||||
|
||||
Use _createValidationMetadata() helper method to create standardized metadata structures.
|
||||
"""
|
||||
|
||||
def __init__(self, services: Any):
|
||||
"""Initialize method with services object"""
|
||||
|
|
@ -168,6 +188,44 @@ class MethodBase:
|
|||
else:
|
||||
return str(type_annotation)
|
||||
|
||||
def _createValidationMetadata(self, actionName: str, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
Helper method to create standardized validationMetadata for ActionDocument instances.
|
||||
|
||||
This method ensures all actions include the required validationMetadata structure
|
||||
for content validation and refinement. Without metadata, results cannot be approved.
|
||||
|
||||
Args:
|
||||
actionName: Name of the action (e.g., "readEmails", "uploadDocument")
|
||||
**kwargs: Additional action-specific metadata fields
|
||||
|
||||
Returns:
|
||||
Dictionary with validationMetadata structure including:
|
||||
- actionType: Full action identifier (moduleName.actionName)
|
||||
- All provided kwargs as additional metadata fields
|
||||
|
||||
Example:
|
||||
validationMetadata = self._createValidationMetadata(
|
||||
"readEmails",
|
||||
connectionReference=connectionReference,
|
||||
folder=folder,
|
||||
limit=limit,
|
||||
emailCount=len(emails)
|
||||
)
|
||||
|
||||
ActionDocument(
|
||||
documentName="emails.json",
|
||||
documentData=json.dumps(data),
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata # REQUIRED
|
||||
)
|
||||
"""
|
||||
metadata = {
|
||||
"actionType": f"{self.name}.{actionName}"
|
||||
}
|
||||
metadata.update(kwargs)
|
||||
return metadata
|
||||
|
||||
def _generateMeaningfulFileName(self, base_name: str, extension: str, workflow_context: Dict[str, Any] = None, action_name: str = None) -> str:
|
||||
"""
|
||||
Generate a meaningful file name with round/task/action information.
|
||||
|
|
|
|||
|
|
@ -78,11 +78,19 @@ class MethodContext(MethodBase):
|
|||
"getDocumentIndex"
|
||||
)
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "context.getDocumentIndex",
|
||||
"resultType": resultType,
|
||||
"workflowId": getattr(workflow, 'id', 'unknown'),
|
||||
"totalDocuments": indexData.get("totalDocuments", 0) if isinstance(indexData, dict) else 0
|
||||
}
|
||||
|
||||
# Create ActionDocument
|
||||
document = ActionDocument(
|
||||
documentName=filename,
|
||||
documentData=indexContent,
|
||||
mimeType="application/json" if resultType == "json" else "text/plain"
|
||||
mimeType="application/json" if resultType == "json" else "text/plain",
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
|
||||
return ActionResult.isSuccess(documents=[document])
|
||||
|
|
@ -313,10 +321,18 @@ class MethodContext(MethodBase):
|
|||
documentName = f"document_{i+1:03d}_extracted_{extracted.id}.json"
|
||||
|
||||
# Store ContentExtracted object in ActionDocument.documentData
|
||||
validationMetadata = {
|
||||
"actionType": "context.extractContent",
|
||||
"documentIndex": i,
|
||||
"extractedId": extracted.id,
|
||||
"partCount": len(extracted.parts) if extracted.parts else 0,
|
||||
"originalFileName": originalDoc.fileName if originalDoc and hasattr(originalDoc, 'fileName') else None
|
||||
}
|
||||
actionDoc = ActionDocument(
|
||||
documentName=documentName,
|
||||
documentData=extracted, # ContentExtracted object
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
actionDocuments.append(actionDoc)
|
||||
|
||||
|
|
|
|||
|
|
@ -465,11 +465,22 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": self.services.utils.timestampGetUtc()
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.readEmails",
|
||||
"connectionReference": connectionReference,
|
||||
"folder": folder,
|
||||
"limit": limit,
|
||||
"filter": filter,
|
||||
"emailCount": email_data.get("count", 0),
|
||||
"outputMimeType": outputMimeType
|
||||
}
|
||||
|
||||
return ActionResult.isSuccess(
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_emails_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
|
||||
|
|
@ -695,12 +706,23 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": self.services.utils.timestampGetUtc()
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.searchEmails",
|
||||
"connectionReference": connectionReference,
|
||||
"query": query,
|
||||
"folder": folder,
|
||||
"limit": limit,
|
||||
"resultCount": search_result.get("count", 0),
|
||||
"outputMimeType": outputMimeType
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_email_search_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
|
||||
|
|
@ -818,12 +840,22 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": self.services.utils.timestampGetUtc()
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.listDrafts",
|
||||
"connectionReference": connectionReference,
|
||||
"folder": folder,
|
||||
"limit": limit,
|
||||
"draftCount": drafts_result.get("count", 0),
|
||||
"outputMimeType": outputMimeType
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_drafts_list_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
|
||||
|
|
@ -928,12 +960,21 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": self.services.utils.timestampGetUtc()
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.findDrafts",
|
||||
"connectionReference": connectionReference,
|
||||
"limit": limit,
|
||||
"totalDrafts": drafts_result.get("totalDrafts", 0),
|
||||
"outputMimeType": outputMimeType
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_drafts_found_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
|
||||
|
|
@ -1069,12 +1110,22 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": self.services.utils.timestampGetUtc()
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.checkDraftsFolder",
|
||||
"connectionReference": connectionReference,
|
||||
"limit": limit,
|
||||
"totalDrafts": drafts_result.get("totalDrafts", 0),
|
||||
"draftsFolderId": drafts_result.get("draftsFolderId"),
|
||||
"outputMimeType": outputMimeType
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_drafts_folder_check_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
|
||||
|
|
@ -1624,34 +1675,61 @@ Return JSON:
|
|||
|
||||
# Determine overall success status
|
||||
if successfulEmails == 0:
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.sendDraftEmail",
|
||||
"connectionReference": connectionReference,
|
||||
"totalEmails": totalEmails,
|
||||
"successfulEmails": successfulEmails,
|
||||
"failedEmails": failedEmails,
|
||||
"status": "all_failed"
|
||||
}
|
||||
return ActionResult.isFailure(
|
||||
error=f"Failed to send all {totalEmails} email(s)",
|
||||
documents=[ActionDocument(
|
||||
documentName=f"sent_mail_confirmation_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
elif failedEmails > 0:
|
||||
# Partial success
|
||||
logger.warning(f"Sent {successfulEmails} out of {totalEmails} emails. {failedEmails} failed.")
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.sendDraftEmail",
|
||||
"connectionReference": connectionReference,
|
||||
"totalEmails": totalEmails,
|
||||
"successfulEmails": successfulEmails,
|
||||
"failedEmails": failedEmails,
|
||||
"status": "partial_success"
|
||||
}
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"sent_mail_confirmation_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
else:
|
||||
# All successful
|
||||
logger.info(f"Successfully sent all {totalEmails} email(s)")
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.sendDraftEmail",
|
||||
"connectionReference": connectionReference,
|
||||
"totalEmails": totalEmails,
|
||||
"successfulEmails": successfulEmails,
|
||||
"failedEmails": failedEmails,
|
||||
"status": "all_successful"
|
||||
}
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"sent_mail_confirmation_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
|
||||
|
|
@ -1693,12 +1771,19 @@ Return JSON:
|
|||
"status": "ready"
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.checkPermissions",
|
||||
"connectionReference": connectionReference,
|
||||
"permissionsStatus": "ready",
|
||||
"hasPermissions": True
|
||||
}
|
||||
return ActionResult(
|
||||
success=True,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_permissions_check_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)]
|
||||
)
|
||||
else:
|
||||
|
|
@ -1711,12 +1796,19 @@ Return JSON:
|
|||
"message": "Please re-authenticate your Microsoft connection to get updated permissions."
|
||||
}
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "outlook.checkPermissions",
|
||||
"connectionReference": connectionReference,
|
||||
"permissionsStatus": "needs_reauthentication",
|
||||
"hasPermissions": False
|
||||
}
|
||||
return ActionResult(
|
||||
success=False,
|
||||
documents=[ActionDocument(
|
||||
documentName=f"outlook_permissions_check_{self._format_timestamp_for_filename()}.json",
|
||||
documentData=json.dumps(result_data, indent=2),
|
||||
mimeType="application/json"
|
||||
mimeType="application/json",
|
||||
validationMetadata=validationMetadata
|
||||
)],
|
||||
error="Connection lacks necessary permissions for Outlook operations"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1072,6 +1072,13 @@ class MethodSharepoint(MethodBase):
|
|||
outputExtension = ".json" # Default
|
||||
outputMimeType = "application/json" # Default
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.findDocumentPath",
|
||||
"searchQuery": searchQuery,
|
||||
"maxResults": maxResults,
|
||||
"totalResults": len(foundDocuments),
|
||||
"hasResults": len(foundDocuments) > 0
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
|
|
@ -1079,7 +1086,8 @@ class MethodSharepoint(MethodBase):
|
|||
ActionDocument(
|
||||
documentName=f"sharepoint_find_path_{self._format_timestamp_for_filename()}{outputExtension}",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType=outputMimeType
|
||||
mimeType=outputMimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
]
|
||||
)
|
||||
|
|
@ -1336,19 +1344,40 @@ class MethodSharepoint(MethodBase):
|
|||
if fileContent and isinstance(fileContent, bytes):
|
||||
# Encode binary content as Base64 string
|
||||
base64Content = base64.b64encode(fileContent).decode('utf-8')
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.readDocuments",
|
||||
"fileName": fileName,
|
||||
"sharepointFileId": resultItem.get("sharepointFileId"),
|
||||
"siteName": resultItem.get("siteName"),
|
||||
"mimeType": mimeType,
|
||||
"contentType": "binary",
|
||||
"size": len(fileContent),
|
||||
"includeMetadata": includeMetadata
|
||||
}
|
||||
actionDoc = ActionDocument(
|
||||
documentName=fileName,
|
||||
documentData=base64Content, # Base64 string for binary files
|
||||
mimeType=mimeType
|
||||
mimeType=mimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
actionDocuments.append(actionDoc)
|
||||
logger.info(f"Stored binary file {fileName} ({len(fileContent)} bytes) as Base64 in ActionDocument")
|
||||
elif fileContent:
|
||||
# Text content - store directly in documentData
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.readDocuments",
|
||||
"fileName": fileName,
|
||||
"sharepointFileId": resultItem.get("sharepointFileId"),
|
||||
"siteName": resultItem.get("siteName"),
|
||||
"mimeType": mimeType,
|
||||
"contentType": "text",
|
||||
"includeMetadata": includeMetadata
|
||||
}
|
||||
actionDoc = ActionDocument(
|
||||
documentName=fileName,
|
||||
documentData=fileContent if isinstance(fileContent, str) else str(fileContent),
|
||||
mimeType=mimeType
|
||||
mimeType=mimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
actionDocuments.append(actionDoc)
|
||||
else:
|
||||
|
|
@ -1366,10 +1395,20 @@ class MethodSharepoint(MethodBase):
|
|||
if resultItem.get("metadata"):
|
||||
docData["metadata"] = resultItem["metadata"]
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.readDocuments",
|
||||
"fileName": fileName,
|
||||
"sharepointFileId": resultItem.get("sharepointFileId"),
|
||||
"siteName": resultItem.get("siteName"),
|
||||
"mimeType": mimeType,
|
||||
"contentType": "metadata_only",
|
||||
"includeMetadata": includeMetadata
|
||||
}
|
||||
actionDoc = ActionDocument(
|
||||
documentName=fileName,
|
||||
documentData=json.dumps(docData, indent=2),
|
||||
mimeType=mimeType
|
||||
mimeType=mimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
actionDocuments.append(actionDoc)
|
||||
|
||||
|
|
@ -1583,6 +1622,13 @@ class MethodSharepoint(MethodBase):
|
|||
outputExtension = ".json" # Default
|
||||
outputMimeType = "application/json" # Default
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.readDocuments",
|
||||
"connectionReference": connectionReference,
|
||||
"documentCount": len(readResults),
|
||||
"includeMetadata": includeMetadata,
|
||||
"sitesSearched": len(sites)
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
|
|
@ -1590,7 +1636,8 @@ class MethodSharepoint(MethodBase):
|
|||
ActionDocument(
|
||||
documentName=f"sharepoint_documents_{self._format_timestamp_for_filename()}{outputExtension}",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType=outputMimeType
|
||||
mimeType=outputMimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
]
|
||||
)
|
||||
|
|
@ -1998,6 +2045,15 @@ class MethodSharepoint(MethodBase):
|
|||
outputExtension = ".json" # Default
|
||||
outputMimeType = "application/json" # Default
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.uploadDocument",
|
||||
"connectionReference": connectionReference,
|
||||
"uploadPath": uploadPath,
|
||||
"fileNames": fileNames,
|
||||
"uploadCount": len(uploadResults),
|
||||
"successfulUploads": len([r for r in uploadResults if r.get("uploadStatus") == "success"]),
|
||||
"failedUploads": len([r for r in uploadResults if r.get("uploadStatus") == "failed"])
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
|
|
@ -2005,7 +2061,8 @@ class MethodSharepoint(MethodBase):
|
|||
ActionDocument(
|
||||
documentName=f"sharepoint_upload_{self._format_timestamp_for_filename()}{outputExtension}",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType=outputMimeType
|
||||
mimeType=outputMimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
]
|
||||
)
|
||||
|
|
@ -2459,6 +2516,14 @@ class MethodSharepoint(MethodBase):
|
|||
outputExtension = ".json" # Default
|
||||
outputMimeType = "application/json" # Default
|
||||
|
||||
validationMetadata = {
|
||||
"actionType": "sharepoint.listDocuments",
|
||||
"pathQuery": listQuery,
|
||||
"includeSubfolders": includeSubfolders,
|
||||
"sitesSearched": len(sites),
|
||||
"folderCount": len(listResults),
|
||||
"totalItems": sum(len(result.get("siteResults", [])) for result in listResults)
|
||||
}
|
||||
|
||||
return ActionResult(
|
||||
success=True,
|
||||
|
|
@ -2466,7 +2531,8 @@ class MethodSharepoint(MethodBase):
|
|||
ActionDocument(
|
||||
documentName=f"sharepoint_document_list_{self._format_timestamp_for_filename()}{outputExtension}",
|
||||
documentData=json.dumps(resultData, indent=2),
|
||||
mimeType=outputMimeType
|
||||
mimeType=outputMimeType,
|
||||
validationMetadata=validationMetadata
|
||||
)
|
||||
]
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue