fixed imports
This commit is contained in:
parent
f02ebead7c
commit
bb9630d6c4
161 changed files with 1318 additions and 1165 deletions
|
|
@ -6,8 +6,8 @@ import re
|
||||||
import time
|
import time
|
||||||
import base64
|
import base64
|
||||||
from typing import Dict, Any, List, Optional, Tuple
|
from typing import Dict, Any, List, Optional, Tuple
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import PromptPlaceholder, ChatDocument
|
from modules.aichat.datamodelFeatureAiChat import PromptPlaceholder, ChatDocument
|
||||||
from modules.features.aichat.serviceExtraction.mainServiceExtraction import ExtractionService
|
from modules.aichat.serviceExtraction.mainServiceExtraction import ExtractionService
|
||||||
from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
||||||
from modules.datamodels.datamodelExtraction import ContentPart, DocumentIntent
|
from modules.datamodels.datamodelExtraction import ContentPart, DocumentIntent
|
||||||
from modules.datamodels.datamodelWorkflow import AiResponse, AiResponseMetadata, DocumentData
|
from modules.datamodels.datamodelWorkflow import AiResponse, AiResponseMetadata, DocumentData
|
||||||
|
|
@ -329,7 +329,7 @@ Respond with ONLY a JSON object in this exact format:
|
||||||
parentOperationId: Optional[str]
|
parentOperationId: Optional[str]
|
||||||
) -> AiResponse:
|
) -> AiResponse:
|
||||||
"""Handle IMAGE_GENERATE operation type using image generation path."""
|
"""Handle IMAGE_GENERATE operation type using image generation path."""
|
||||||
from modules.features.aichat.serviceGeneration.paths.imagePath import ImageGenerationPath
|
from modules.aichat.serviceGeneration.paths.imagePath import ImageGenerationPath
|
||||||
|
|
||||||
imagePath = ImageGenerationPath(self.services)
|
imagePath = ImageGenerationPath(self.services)
|
||||||
|
|
||||||
|
|
@ -514,7 +514,7 @@ Respond with ONLY a JSON object in this exact format:
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from modules.features.aichat.serviceGeneration.mainServiceGeneration import GenerationService
|
from modules.aichat.serviceGeneration.mainServiceGeneration import GenerationService
|
||||||
|
|
||||||
generationService = GenerationService(self.services)
|
generationService = GenerationService(self.services)
|
||||||
|
|
||||||
|
|
@ -829,7 +829,7 @@ Respond with ONLY a JSON object in this exact format:
|
||||||
parentOperationId: Optional[str]
|
parentOperationId: Optional[str]
|
||||||
) -> AiResponse:
|
) -> AiResponse:
|
||||||
"""Handle code generation using code generation path."""
|
"""Handle code generation using code generation path."""
|
||||||
from modules.features.aichat.serviceGeneration.paths.codePath import CodeGenerationPath
|
from modules.aichat.serviceGeneration.paths.codePath import CodeGenerationPath
|
||||||
|
|
||||||
codePath = CodeGenerationPath(self.services)
|
codePath = CodeGenerationPath(self.services)
|
||||||
return await codePath.generateCode(
|
return await codePath.generateCode(
|
||||||
|
|
@ -852,7 +852,7 @@ Respond with ONLY a JSON object in this exact format:
|
||||||
parentOperationId: Optional[str]
|
parentOperationId: Optional[str]
|
||||||
) -> AiResponse:
|
) -> AiResponse:
|
||||||
"""Handle document generation using document generation path."""
|
"""Handle document generation using document generation path."""
|
||||||
from modules.features.aichat.serviceGeneration.paths.documentPath import DocumentGenerationPath
|
from modules.aichat.serviceGeneration.paths.documentPath import DocumentGenerationPath
|
||||||
|
|
||||||
# Set compression options for document generation
|
# Set compression options for document generation
|
||||||
options.compressPrompt = False
|
options.compressPrompt = False
|
||||||
|
|
@ -14,7 +14,7 @@ import logging
|
||||||
import base64
|
import base64
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
|
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatDocument
|
from modules.aichat.datamodelFeatureAiChat import ChatDocument
|
||||||
from modules.datamodels.datamodelExtraction import ContentPart, DocumentIntent
|
from modules.datamodels.datamodelExtraction import ContentPart, DocumentIntent
|
||||||
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
|
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
|
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatDocument
|
from modules.aichat.datamodelFeatureAiChat import ChatDocument
|
||||||
from modules.datamodels.datamodelExtraction import DocumentIntent
|
from modules.datamodels.datamodelExtraction import DocumentIntent
|
||||||
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
|
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
|
||||||
|
|
||||||
|
|
@ -2531,7 +2531,7 @@ CRITICAL:
|
||||||
List of accepted section content types (e.g., ["table", "code_block"])
|
List of accepted section content types (e.g., ["table", "code_block"])
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from modules.features.aichat.serviceGeneration.renderers.registry import getRenderer
|
from modules.aichat.serviceGeneration.renderers.registry import getRenderer
|
||||||
|
|
||||||
# Get renderer for this format
|
# Get renderer for this format
|
||||||
renderer = getRenderer(outputFormat, self.services)
|
renderer = getRenderer(outputFormat, self.services)
|
||||||
|
|
@ -231,7 +231,7 @@ CRITICAL:
|
||||||
raise ValueError("Structure has no documents - cannot generate without documents")
|
raise ValueError("Structure has no documents - cannot generate without documents")
|
||||||
|
|
||||||
# Import renderer registry for format validation (existing infrastructure)
|
# Import renderer registry for format validation (existing infrastructure)
|
||||||
from modules.features.aichat.serviceGeneration.renderers.registry import getRenderer
|
from modules.aichat.serviceGeneration.renderers.registry import getRenderer
|
||||||
|
|
||||||
# Validate and fix each document
|
# Validate and fix each document
|
||||||
for doc in documents:
|
for doc in documents:
|
||||||
|
|
@ -11,10 +11,10 @@ import json
|
||||||
from .subRegistry import ExtractorRegistry, ChunkerRegistry
|
from .subRegistry import ExtractorRegistry, ChunkerRegistry
|
||||||
from .subPipeline import runExtraction
|
from .subPipeline import runExtraction
|
||||||
from modules.datamodels.datamodelExtraction import ContentExtracted, ContentPart, MergeStrategy, ExtractionOptions, PartResult, DocumentIntent
|
from modules.datamodels.datamodelExtraction import ContentExtracted, ContentPart, MergeStrategy, ExtractionOptions, PartResult, DocumentIntent
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatDocument
|
from modules.aichat.datamodelFeatureAiChat import ChatDocument
|
||||||
from modules.datamodels.datamodelAi import AiCallResponse, AiCallRequest, AiCallOptions, OperationTypeEnum, AiModelCall
|
from modules.datamodels.datamodelAi import AiCallResponse, AiCallRequest, AiCallOptions, OperationTypeEnum, AiModelCall
|
||||||
from modules.features.aichat.aicore.aicoreModelRegistry import modelRegistry
|
from modules.aichat.aicore.aicoreModelRegistry import modelRegistry
|
||||||
from modules.features.aichat.aicore.aicoreModelSelector import modelSelector
|
from modules.aichat.aicore.aicoreModelSelector import modelSelector
|
||||||
from modules.shared.jsonUtils import stripCodeFences
|
from modules.shared.jsonUtils import stripCodeFences
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, Operati
|
||||||
# Type hint for renderer parameter
|
# Type hint for renderer parameter
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from modules.features.aichat.serviceGeneration.renderers.documentRendererBaseTemplate import BaseRenderer
|
from modules.aichat.serviceGeneration.renderers.documentRendererBaseTemplate import BaseRenderer
|
||||||
_RendererLike = BaseRenderer
|
_RendererLike = BaseRenderer
|
||||||
else:
|
else:
|
||||||
_RendererLike = Any
|
_RendererLike = Any
|
||||||
|
|
@ -71,7 +71,7 @@ class ExtractorRegistry:
|
||||||
module_name = file_path.stem
|
module_name = file_path.stem
|
||||||
try:
|
try:
|
||||||
# Import the module
|
# Import the module
|
||||||
module = importlib.import_module(f".{module_name}", package="modules.features.aichat.serviceExtraction.extractors")
|
module = importlib.import_module(f".{module_name}", package="modules.aichat.serviceExtraction.extractors")
|
||||||
|
|
||||||
# Find all extractor classes in the module
|
# Find all extractor classes in the module
|
||||||
for attr_name in dir(module):
|
for attr_name in dir(module):
|
||||||
|
|
@ -6,8 +6,8 @@ import base64
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Any, Dict, List, Optional, Callable
|
from typing import Any, Dict, List, Optional, Callable
|
||||||
from modules.datamodels.datamodelDocument import RenderedDocument
|
from modules.datamodels.datamodelDocument import RenderedDocument
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatDocument
|
from modules.aichat.datamodelFeatureAiChat import ChatDocument
|
||||||
from modules.features.aichat.serviceGeneration.subDocumentUtility import (
|
from modules.aichat.serviceGeneration.subDocumentUtility import (
|
||||||
getFileExtension,
|
getFileExtension,
|
||||||
getMimeTypeFromExtension,
|
getMimeTypeFromExtension,
|
||||||
detectMimeTypeFromContent,
|
detectMimeTypeFromContent,
|
||||||
|
|
@ -414,7 +414,7 @@ class GenerationService:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check output style classification (code/document/image/etc.) from renderer
|
# Check output style classification (code/document/image/etc.) from renderer
|
||||||
from modules.features.aichat.serviceGeneration.renderers.registry import getOutputStyle
|
from modules.aichat.serviceGeneration.renderers.registry import getOutputStyle
|
||||||
outputStyle = getOutputStyle(docFormat)
|
outputStyle = getOutputStyle(docFormat)
|
||||||
if outputStyle:
|
if outputStyle:
|
||||||
logger.debug(f"Document {doc.get('id', docIndex)} format '{docFormat}' classified as '{outputStyle}' style")
|
logger.debug(f"Document {doc.get('id', docIndex)} format '{docFormat}' classified as '{outputStyle}' style")
|
||||||
|
|
@ -471,8 +471,8 @@ class GenerationService:
|
||||||
Complete document structure with populated elements ready for rendering
|
Complete document structure with populated elements ready for rendering
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from modules.features.aichat.serviceGeneration.subStructureGenerator import StructureGenerator
|
from modules.aichat.serviceGeneration.subStructureGenerator import StructureGenerator
|
||||||
from modules.features.aichat.serviceGeneration.subContentGenerator import ContentGenerator
|
from modules.aichat.serviceGeneration.subContentGenerator import ContentGenerator
|
||||||
|
|
||||||
# Phase 1: Generate structure skeleton
|
# Phase 1: Generate structure skeleton
|
||||||
if progressCallback:
|
if progressCallback:
|
||||||
|
|
@ -537,7 +537,7 @@ class GenerationService:
|
||||||
aiService=None
|
aiService=None
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Get adaptive extraction prompt."""
|
"""Get adaptive extraction prompt."""
|
||||||
from modules.features.aichat.serviceExtraction.subPromptBuilderExtraction import buildExtractionPrompt
|
from modules.aichat.serviceExtraction.subPromptBuilderExtraction import buildExtractionPrompt
|
||||||
return await buildExtractionPrompt(
|
return await buildExtractionPrompt(
|
||||||
outputFormat=outputFormat,
|
outputFormat=outputFormat,
|
||||||
userPrompt=userPrompt,
|
userPrompt=userPrompt,
|
||||||
|
|
@ -920,7 +920,7 @@ CRITICAL:
|
||||||
|
|
||||||
def _getCodeRenderer(self, fileType: str):
|
def _getCodeRenderer(self, fileType: str):
|
||||||
"""Get code renderer for file type."""
|
"""Get code renderer for file type."""
|
||||||
from modules.features.aichat.serviceGeneration.renderers.registry import getRenderer
|
from modules.aichat.serviceGeneration.renderers.registry import getRenderer
|
||||||
|
|
||||||
# Map file types to renderer formats
|
# Map file types to renderer formats
|
||||||
formatMap = {
|
formatMap = {
|
||||||
|
|
@ -12,7 +12,7 @@ import base64
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Dict, Any, Optional, List, Callable
|
from typing import Dict, Any, Optional, List, Callable
|
||||||
from modules.features.aichat.serviceGeneration.subContentIntegrator import ContentIntegrator
|
from modules.aichat.serviceGeneration.subContentIntegrator import ContentIntegrator
|
||||||
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
|
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
from typing import Optional, Any, Union, List, Dict, Callable, Awaitable
|
from typing import Optional, Any, Union, List, Dict, Callable, Awaitable
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from modules.datamodels.datamodelChat import ActionResult
|
from modules.aichat.datamodelFeatureAiChat import ActionResult
|
||||||
from modules.shared.frontendTypes import FrontendType
|
from modules.shared.frontendTypes import FrontendType
|
||||||
from modules.shared.attributeUtils import registerModelLabels
|
from modules.shared.attributeUtils import registerModelLabels
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ import logging
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# Import interfaces and models
|
# Import interfaces and models
|
||||||
from modules.features.aichat.interfaceFeatureAiChat import getInterface as getChatInterface
|
from modules.aichat.interfaceFeatureAiChat import getInterface as getChatInterface
|
||||||
from modules.auth import getCurrentUser, limiter
|
from modules.auth import getCurrentUser, limiter
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import AutomationDefinition, ChatWorkflow
|
from modules.aichat.datamodelFeatureAiChat import AutomationDefinition, ChatWorkflow
|
||||||
from modules.datamodels.datamodelPagination import PaginationParams, PaginatedResponse, PaginationMetadata, normalize_pagination_dict
|
from modules.datamodels.datamodelPagination import PaginationParams, PaginatedResponse, PaginationMetadata, normalize_pagination_dict
|
||||||
from modules.shared.attributeUtils import getModelAttributeDefinitions
|
from modules.shared.attributeUtils import getModelAttributeDefinitions
|
||||||
from modules.workflows.automation import executeAutomation
|
from modules.workflows.automation import executeAutomation
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ import asyncio
|
||||||
import re
|
import re
|
||||||
from typing import Optional, Dict, Any, List
|
from typing import Optional, Dict, Any, List
|
||||||
|
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum, ChatLog, ChatDocument
|
from modules.aichat.datamodelFeatureAiChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum, ChatLog, ChatDocument
|
||||||
from modules.datamodels.datamodelUam import User
|
from modules.datamodels.datamodelUam import User
|
||||||
from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, ProcessingModeEnum
|
from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, ProcessingModeEnum
|
||||||
from modules.datamodels.datamodelDocref import DocumentReferenceList, DocumentItemReference
|
from modules.datamodels.datamodelDocref import DocumentReferenceList, DocumentItemReference
|
||||||
|
|
@ -439,7 +439,7 @@ async def _emit_log_and_event(
|
||||||
# Emit event directly for streaming (using correct signature)
|
# Emit event directly for streaming (using correct signature)
|
||||||
if created_log and event_manager:
|
if created_log and event_manager:
|
||||||
try:
|
try:
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatLog
|
from modules.aichat.datamodelFeatureAiChat import ChatLog
|
||||||
# Convert to dict if it's a Pydantic model
|
# Convert to dict if it's a Pydantic model
|
||||||
if hasattr(created_log, "model_dump"):
|
if hasattr(created_log, "model_dump"):
|
||||||
log_dict = created_log.model_dump()
|
log_dict = created_log.model_dump()
|
||||||
|
|
|
||||||
176
modules/features/neutralizer/interfaceFeatureNeutralizer.py
Normal file
176
modules/features/neutralizer/interfaceFeatureNeutralizer.py
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
# Copyright (c) 2025 Patrick Motsch
|
||||||
|
# All rights reserved.
|
||||||
|
"""
|
||||||
|
Database interface for the Neutralizer feature.
|
||||||
|
Handles CRUD operations for neutralization configuration and attributes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Dict, List, Any, Optional
|
||||||
|
|
||||||
|
from modules.features.neutralizer.datamodelFeatureNeutralizer import (
|
||||||
|
DataNeutraliserConfig,
|
||||||
|
DataNeutralizerAttributes,
|
||||||
|
)
|
||||||
|
from modules.interfaces.interfaceRbac import getRecordsetWithRBAC
|
||||||
|
from modules.shared.timeUtils import getUtcTimestamp
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceFeatureNeutralizer:
|
||||||
|
"""Database interface for Neutralizer feature operations"""
|
||||||
|
|
||||||
|
def __init__(self, db, currentUser, mandateId: str, userId: str):
|
||||||
|
"""
|
||||||
|
Initialize the interface with database connection and user context.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
db: Database connection instance
|
||||||
|
currentUser: Current user object for RBAC
|
||||||
|
mandateId: Current mandate ID
|
||||||
|
userId: Current user ID
|
||||||
|
"""
|
||||||
|
self.db = db
|
||||||
|
self.currentUser = currentUser
|
||||||
|
self.mandateId = mandateId
|
||||||
|
self.userId = userId
|
||||||
|
|
||||||
|
def getNeutralizationConfig(self) -> Optional[DataNeutraliserConfig]:
|
||||||
|
"""Get the data neutralization configuration for the current user's mandate"""
|
||||||
|
try:
|
||||||
|
# Use RBAC filtering
|
||||||
|
filteredConfigs = getRecordsetWithRBAC(
|
||||||
|
self.db,
|
||||||
|
DataNeutraliserConfig,
|
||||||
|
self.currentUser,
|
||||||
|
recordFilter={"mandateId": self.mandateId}
|
||||||
|
)
|
||||||
|
|
||||||
|
if not filteredConfigs:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Filter out database-specific fields
|
||||||
|
configDict = filteredConfigs[0]
|
||||||
|
cleanedConfig = {k: v for k, v in configDict.items() if not k.startswith("_")}
|
||||||
|
return DataNeutraliserConfig(**cleanedConfig)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting neutralization config: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def createOrUpdateNeutralizationConfig(
|
||||||
|
self, configData: Dict[str, Any]
|
||||||
|
) -> DataNeutraliserConfig:
|
||||||
|
"""Create or update the data neutralization configuration"""
|
||||||
|
try:
|
||||||
|
# Check if config already exists
|
||||||
|
existingConfig = self.getNeutralizationConfig()
|
||||||
|
|
||||||
|
if existingConfig:
|
||||||
|
# Update existing config
|
||||||
|
updateData = existingConfig.model_dump()
|
||||||
|
updateData.update(configData)
|
||||||
|
updateData["updatedAt"] = getUtcTimestamp()
|
||||||
|
|
||||||
|
updatedConfig = DataNeutraliserConfig(**updateData)
|
||||||
|
self.db.recordModify(
|
||||||
|
DataNeutraliserConfig, existingConfig.id, updatedConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
return updatedConfig
|
||||||
|
else:
|
||||||
|
# Create new config
|
||||||
|
configData["mandateId"] = self.mandateId
|
||||||
|
configData["userId"] = self.userId
|
||||||
|
|
||||||
|
newConfig = DataNeutraliserConfig(**configData)
|
||||||
|
createdRecord = self.db.recordCreate(DataNeutraliserConfig, newConfig)
|
||||||
|
|
||||||
|
return DataNeutraliserConfig(**createdRecord)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error creating/updating neutralization config: {str(e)}")
|
||||||
|
raise ValueError(f"Failed to create/update neutralization config: {str(e)}")
|
||||||
|
|
||||||
|
def getNeutralizationAttributes(
|
||||||
|
self, fileId: Optional[str] = None
|
||||||
|
) -> List[DataNeutralizerAttributes]:
|
||||||
|
"""Get neutralization attributes, optionally filtered by file ID"""
|
||||||
|
try:
|
||||||
|
filterDict = {"mandateId": self.mandateId}
|
||||||
|
if fileId:
|
||||||
|
filterDict["fileId"] = fileId
|
||||||
|
|
||||||
|
# Use RBAC filtering
|
||||||
|
filteredAttributes = getRecordsetWithRBAC(
|
||||||
|
self.db,
|
||||||
|
DataNeutralizerAttributes,
|
||||||
|
self.currentUser,
|
||||||
|
recordFilter=filterDict
|
||||||
|
)
|
||||||
|
|
||||||
|
# Filter out database-specific fields
|
||||||
|
cleanedAttributes = []
|
||||||
|
for attr in filteredAttributes:
|
||||||
|
cleanedAttr = {k: v for k, v in attr.items() if not k.startswith("_")}
|
||||||
|
cleanedAttributes.append(cleanedAttr)
|
||||||
|
|
||||||
|
return [
|
||||||
|
DataNeutralizerAttributes(**attr)
|
||||||
|
for attr in cleanedAttributes
|
||||||
|
]
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting neutralization attributes: {str(e)}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def deleteNeutralizationAttributes(self, fileId: str) -> bool:
|
||||||
|
"""Delete all neutralization attributes for a specific file"""
|
||||||
|
try:
|
||||||
|
attributes = self.db.getRecordset(
|
||||||
|
DataNeutralizerAttributes,
|
||||||
|
recordFilter={"mandateId": self.mandateId, "fileId": fileId},
|
||||||
|
)
|
||||||
|
|
||||||
|
for attribute in attributes:
|
||||||
|
self.db.recordDelete(DataNeutralizerAttributes, attribute["id"])
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Deleted {len(attributes)} neutralization attributes for file {fileId}"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error deleting neutralization attributes: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getAttributeById(self, attributeId: str) -> Optional[Dict[str, Any]]:
|
||||||
|
"""Get a single neutralization attribute by ID"""
|
||||||
|
try:
|
||||||
|
attributes = self.db.getRecordset(
|
||||||
|
DataNeutralizerAttributes,
|
||||||
|
recordFilter={"mandateId": self.mandateId, "id": attributeId}
|
||||||
|
)
|
||||||
|
if attributes:
|
||||||
|
return attributes[0]
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting attribute by ID: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def getInterface(db, currentUser, mandateId: str, userId: str) -> InterfaceFeatureNeutralizer:
|
||||||
|
"""
|
||||||
|
Factory function to create a Neutralizer interface instance.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
db: Database connection
|
||||||
|
currentUser: Current user for RBAC
|
||||||
|
mandateId: Current mandate ID
|
||||||
|
userId: Current user ID
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
InterfaceFeatureNeutralizer instance
|
||||||
|
"""
|
||||||
|
return InterfaceFeatureNeutralizer(db, currentUser, mandateId, userId)
|
||||||
|
|
@ -14,6 +14,7 @@ import json
|
||||||
from typing import Dict, List, Any, Optional
|
from typing import Dict, List, Any, Optional
|
||||||
|
|
||||||
from modules.features.neutralizer.datamodelFeatureNeutralizer import DataNeutraliserConfig, DataNeutralizerAttributes
|
from modules.features.neutralizer.datamodelFeatureNeutralizer import DataNeutraliserConfig, DataNeutralizerAttributes
|
||||||
|
from modules.features.neutralizer.interfaceFeatureNeutralizer import InterfaceFeatureNeutralizer
|
||||||
|
|
||||||
# Import all necessary classes and functions for neutralization
|
# Import all necessary classes and functions for neutralization
|
||||||
from .subProcessCommon import CommonUtils, NeutralizationResult, NeutralizationAttribute
|
from .subProcessCommon import CommonUtils, NeutralizationResult, NeutralizationAttribute
|
||||||
|
|
@ -35,9 +36,19 @@ class NeutralizationService:
|
||||||
NamesToParse: List of names to parse and replace (case-insensitive)
|
NamesToParse: List of names to parse and replace (case-insensitive)
|
||||||
"""
|
"""
|
||||||
self.services = serviceCenter
|
self.services = serviceCenter
|
||||||
self.interfaceDbApp = serviceCenter.interfaceDbApp
|
|
||||||
self.interfaceDbComponent = serviceCenter.interfaceDbComponent
|
self.interfaceDbComponent = serviceCenter.interfaceDbComponent
|
||||||
|
|
||||||
|
# Create feature-specific interface for neutralizer DB operations
|
||||||
|
self.interfaceNeutralizer: InterfaceFeatureNeutralizer = None
|
||||||
|
if serviceCenter and serviceCenter.interfaceDbApp:
|
||||||
|
dbApp = serviceCenter.interfaceDbApp
|
||||||
|
self.interfaceNeutralizer = InterfaceFeatureNeutralizer(
|
||||||
|
db=dbApp.db,
|
||||||
|
currentUser=dbApp.currentUser,
|
||||||
|
mandateId=dbApp.mandateId,
|
||||||
|
userId=dbApp.userId
|
||||||
|
)
|
||||||
|
|
||||||
# Initialize anonymization processors
|
# Initialize anonymization processors
|
||||||
self.NamesToParse = NamesToParse or []
|
self.NamesToParse = NamesToParse or []
|
||||||
self.textProcessor = TextProcessor(NamesToParse)
|
self.textProcessor = TextProcessor(NamesToParse)
|
||||||
|
|
@ -47,15 +58,15 @@ class NeutralizationService:
|
||||||
|
|
||||||
def getConfig(self) -> Optional[DataNeutraliserConfig]:
|
def getConfig(self) -> Optional[DataNeutraliserConfig]:
|
||||||
"""Get the neutralization configuration for the current user's mandate"""
|
"""Get the neutralization configuration for the current user's mandate"""
|
||||||
if not self.interfaceDbApp:
|
if not self.interfaceNeutralizer:
|
||||||
return None
|
return None
|
||||||
return self.interfaceDbApp.getNeutralizationConfig()
|
return self.interfaceNeutralizer.getNeutralizationConfig()
|
||||||
|
|
||||||
def saveConfig(self, config_data: Dict[str, Any]) -> DataNeutraliserConfig:
|
def saveConfig(self, configData: Dict[str, Any]) -> DataNeutraliserConfig:
|
||||||
"""Save or update the neutralization configuration"""
|
"""Save or update the neutralization configuration"""
|
||||||
if not self.interfaceDbApp:
|
if not self.interfaceNeutralizer:
|
||||||
raise ValueError("User context required for saving configuration")
|
raise ValueError("User context required for saving configuration")
|
||||||
return self.interfaceDbApp.createOrUpdateNeutralizationConfig(config_data)
|
return self.interfaceNeutralizer.createOrUpdateNeutralizationConfig(configData)
|
||||||
|
|
||||||
# Public API: process text or file
|
# Public API: process text or file
|
||||||
|
|
||||||
|
|
@ -125,44 +136,37 @@ class NeutralizationService:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def resolveText(self, text: str) -> str:
|
def resolveText(self, text: str) -> str:
|
||||||
if not self.interfaceDbApp:
|
if not self.interfaceNeutralizer:
|
||||||
return text
|
return text
|
||||||
try:
|
try:
|
||||||
placeholder_pattern = r'\[([a-z]+)\.([a-f0-9-]{36})\]'
|
placeholderPattern = r'\[([a-z]+)\.([a-f0-9-]{36})\]'
|
||||||
matches = re.findall(placeholder_pattern, text)
|
matches = re.findall(placeholderPattern, text)
|
||||||
resolved_text = text
|
resolvedText = text
|
||||||
for placeholder_type, uid in matches:
|
for placeholderType, uid in matches:
|
||||||
attributes = self.interfaceDbApp.db.getRecordset(
|
attribute = self.interfaceNeutralizer.getAttributeById(uid)
|
||||||
DataNeutralizerAttributes,
|
if attribute:
|
||||||
recordFilter={
|
placeholder = f"[{placeholderType}.{uid}]"
|
||||||
"mandateId": self.interfaceDbApp.mandateId,
|
resolvedText = resolvedText.replace(placeholder, attribute["originalText"])
|
||||||
"id": uid
|
return resolvedText
|
||||||
}
|
|
||||||
)
|
|
||||||
if attributes:
|
|
||||||
attribute = attributes[0]
|
|
||||||
placeholder = f"[{placeholder_type}.{uid}]"
|
|
||||||
resolved_text = resolved_text.replace(placeholder, attribute["originalText"])
|
|
||||||
return resolved_text
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def getAttributes(self) -> List[DataNeutralizerAttributes]:
|
def getAttributes(self) -> List[DataNeutralizerAttributes]:
|
||||||
"""Get all neutralization attributes for the current user's mandate"""
|
"""Get all neutralization attributes for the current user's mandate"""
|
||||||
if not self.interfaceDbApp:
|
if not self.interfaceNeutralizer:
|
||||||
return []
|
return []
|
||||||
try:
|
try:
|
||||||
# Use the interface method which properly converts dicts to objects
|
# Use the interface method which properly converts dicts to objects
|
||||||
return self.interfaceDbApp.getNeutralizationAttributes()
|
return self.interfaceNeutralizer.getNeutralizationAttributes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error getting neutralization attributes: {str(e)}")
|
logger.error(f"Error getting neutralization attributes: {str(e)}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def deleteNeutralizationAttributes(self, fileId: str) -> bool:
|
def deleteNeutralizationAttributes(self, fileId: str) -> bool:
|
||||||
"""Delete neutralization attributes for a specific file"""
|
"""Delete neutralization attributes for a specific file"""
|
||||||
if not self.interfaceDbApp:
|
if not self.interfaceNeutralizer:
|
||||||
return False
|
return False
|
||||||
return self.interfaceDbApp.deleteNeutralizationAttributes(fileId)
|
return self.interfaceNeutralizer.deleteNeutralizationAttributes(fileId)
|
||||||
|
|
||||||
def _reloadNamesFromConfig(self) -> None:
|
def _reloadNamesFromConfig(self) -> None:
|
||||||
"""Reload names from config and update processors"""
|
"""Reload names from config and update processors"""
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import time
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
from modules.features.aichat.aicore.aicoreModelRegistry import modelRegistry
|
from modules.aichat.aicore.aicoreModelRegistry import modelRegistry
|
||||||
from modules.features.aichat.aicore.aicoreModelSelector import modelSelector
|
from modules.aichat.aicore.aicoreModelSelector import modelSelector
|
||||||
from modules.datamodels.datamodelAi import (
|
from modules.datamodels.datamodelAi import (
|
||||||
AiModel,
|
AiModel,
|
||||||
AiCallOptions,
|
AiCallOptions,
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,6 @@ from modules.datamodels.datamodelRbac import (
|
||||||
)
|
)
|
||||||
from modules.datamodels.datamodelUam import AccessLevel
|
from modules.datamodels.datamodelUam import AccessLevel
|
||||||
from modules.datamodels.datamodelSecurity import Token, AuthEvent, TokenStatus
|
from modules.datamodels.datamodelSecurity import Token, AuthEvent, TokenStatus
|
||||||
from modules.features.neutralizer.datamodelFeatureNeutralizer import (
|
|
||||||
DataNeutraliserConfig,
|
|
||||||
DataNeutralizerAttributes,
|
|
||||||
)
|
|
||||||
from modules.datamodels.datamodelPagination import PaginationParams, PaginatedResult
|
from modules.datamodels.datamodelPagination import PaginationParams, PaginatedResult
|
||||||
from modules.datamodels.datamodelMembership import (
|
from modules.datamodels.datamodelMembership import (
|
||||||
UserMandate,
|
UserMandate,
|
||||||
|
|
@ -2040,115 +2036,6 @@ class AppObjects:
|
||||||
logger.error(f"Error during logout: {str(e)}")
|
logger.error(f"Error during logout: {str(e)}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# Neutralization methods
|
|
||||||
|
|
||||||
def getNeutralizationConfig(self) -> Optional[DataNeutraliserConfig]:
|
|
||||||
"""Get the data neutralization configuration for the current user's mandate"""
|
|
||||||
try:
|
|
||||||
# Use RBAC filtering
|
|
||||||
filtered_configs = getRecordsetWithRBAC(self.db,
|
|
||||||
DataNeutraliserConfig,
|
|
||||||
self.currentUser,
|
|
||||||
recordFilter={"mandateId": self.mandateId}
|
|
||||||
)
|
|
||||||
|
|
||||||
if not filtered_configs:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Filter out database-specific fields
|
|
||||||
configDict = filtered_configs[0]
|
|
||||||
cleanedConfig = {k: v for k, v in configDict.items() if not k.startswith("_")}
|
|
||||||
return DataNeutraliserConfig(**cleanedConfig)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting neutralization config: {str(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def createOrUpdateNeutralizationConfig(
|
|
||||||
self, config_data: Dict[str, Any]
|
|
||||||
) -> DataNeutraliserConfig:
|
|
||||||
"""Create or update the data neutralization configuration"""
|
|
||||||
try:
|
|
||||||
# Check if config already exists
|
|
||||||
existing_config = self.getNeutralizationConfig()
|
|
||||||
|
|
||||||
if existing_config:
|
|
||||||
# Update existing config
|
|
||||||
update_data = existing_config.model_dump()
|
|
||||||
update_data.update(config_data)
|
|
||||||
update_data["updatedAt"] = getUtcTimestamp()
|
|
||||||
|
|
||||||
updated_config = DataNeutraliserConfig(**update_data)
|
|
||||||
self.db.recordModify(
|
|
||||||
DataNeutraliserConfig, existing_config.id, updated_config
|
|
||||||
)
|
|
||||||
|
|
||||||
return updated_config
|
|
||||||
else:
|
|
||||||
# Create new config
|
|
||||||
config_data["mandateId"] = self.mandateId
|
|
||||||
config_data["userId"] = self.userId
|
|
||||||
|
|
||||||
new_config = DataNeutraliserConfig(**config_data)
|
|
||||||
created_record = self.db.recordCreate(DataNeutraliserConfig, new_config)
|
|
||||||
|
|
||||||
return DataNeutraliserConfig(**created_record)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error creating/updating neutralization config: {str(e)}")
|
|
||||||
raise ValueError(f"Failed to create/update neutralization config: {str(e)}")
|
|
||||||
|
|
||||||
def getNeutralizationAttributes(
|
|
||||||
self, file_id: Optional[str] = None
|
|
||||||
) -> List[DataNeutralizerAttributes]:
|
|
||||||
"""Get neutralization attributes, optionally filtered by file ID"""
|
|
||||||
try:
|
|
||||||
filter_dict = {"mandateId": self.mandateId}
|
|
||||||
if file_id:
|
|
||||||
filter_dict["fileId"] = file_id
|
|
||||||
|
|
||||||
# Use RBAC filtering
|
|
||||||
filtered_attributes = getRecordsetWithRBAC(self.db,
|
|
||||||
DataNeutralizerAttributes,
|
|
||||||
self.currentUser,
|
|
||||||
recordFilter=filter_dict
|
|
||||||
)
|
|
||||||
|
|
||||||
# Filter out database-specific fields
|
|
||||||
cleaned_attributes = []
|
|
||||||
for attr in filtered_attributes:
|
|
||||||
cleanedAttr = {k: v for k, v in attr.items() if not k.startswith("_")}
|
|
||||||
cleaned_attributes.append(cleanedAttr)
|
|
||||||
|
|
||||||
return [
|
|
||||||
DataNeutralizerAttributes(**attr)
|
|
||||||
for attr in cleaned_attributes
|
|
||||||
]
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error getting neutralization attributes: {str(e)}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
def deleteNeutralizationAttributes(self, file_id: str) -> bool:
|
|
||||||
"""Delete all neutralization attributes for a specific file"""
|
|
||||||
try:
|
|
||||||
attributes = self.db.getRecordset(
|
|
||||||
DataNeutralizerAttributes,
|
|
||||||
recordFilter={"mandateId": self.mandateId, "fileId": file_id},
|
|
||||||
)
|
|
||||||
|
|
||||||
for attribute in attributes:
|
|
||||||
self.db.recordDelete(DataNeutralizerAttributes, attribute["id"])
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
f"Deleted {len(attributes)} neutralization attributes for file {file_id}"
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error deleting neutralization attributes: {str(e)}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# RBAC CRUD Methods
|
# RBAC CRUD Methods
|
||||||
|
|
||||||
def createAccessRule(self, accessRule: AccessRule) -> AccessRule:
|
def createAccessRule(self, accessRule: AccessRule) -> AccessRule:
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ from fastapi import status
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# Import interfaces and models from feature containers
|
# Import interfaces and models from feature containers
|
||||||
import modules.features.aichat.interfaceFeatureAiChat as interfaceDbChat
|
import modules.aichat.interfaceFeatureAiChat as interfaceDbChat
|
||||||
from modules.auth import limiter, getRequestContext, requireSysAdmin, RequestContext
|
from modules.auth import limiter, getRequestContext, requireSysAdmin, RequestContext
|
||||||
from modules.datamodels.datamodelUam import User
|
from modules.datamodels.datamodelUam import User
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ async def sync_all_automation_events(
|
||||||
This will register/remove events based on active flags.
|
This will register/remove events based on active flags.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from modules.features.aichat.interfaceFeatureAiChat import getInterface as getChatInterface
|
from modules.aichat.interfaceFeatureAiChat import getInterface as getChatInterface
|
||||||
from modules.interfaces.interfaceDbApp import getRootInterface
|
from modules.interfaces.interfaceDbApp import getRootInterface
|
||||||
from modules.workflows.automation import syncAutomationEvents
|
from modules.workflows.automation import syncAutomationEvents
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ from fastapi import APIRouter, HTTPException, Depends, Body, Path, Query, Respon
|
||||||
from modules.auth import limiter, getCurrentUser
|
from modules.auth import limiter, getCurrentUser
|
||||||
|
|
||||||
# Import interfaces from feature containers
|
# Import interfaces from feature containers
|
||||||
import modules.features.aichat.interfaceFeatureAiChat as interfaceDbChat
|
import modules.aichat.interfaceFeatureAiChat as interfaceDbChat
|
||||||
from modules.features.aichat.interfaceFeatureAiChat import getInterface
|
from modules.aichat.interfaceFeatureAiChat import getInterface
|
||||||
from modules.interfaces.interfaceRbac import getRecordsetWithRBAC
|
from modules.interfaces.interfaceRbac import getRecordsetWithRBAC
|
||||||
|
|
||||||
# Import models from feature containers
|
# Import models from feature containers
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import (
|
from modules.aichat.datamodelFeatureAiChat import (
|
||||||
ChatWorkflow,
|
ChatWorkflow,
|
||||||
ChatMessage,
|
ChatMessage,
|
||||||
ChatLog,
|
ChatLog,
|
||||||
|
|
|
||||||
54
modules/security/passwordUtils.py
Normal file
54
modules/security/passwordUtils.py
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Copyright (c) 2025 Patrick Motsch
|
||||||
|
# All rights reserved.
|
||||||
|
"""
|
||||||
|
Password utility functions for secure password handling.
|
||||||
|
Uses Argon2 for password hashing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
from passlib.context import CryptContext
|
||||||
|
|
||||||
|
# Password hashing context using Argon2
|
||||||
|
_pwdContext = CryptContext(schemes=["argon2"], deprecated="auto")
|
||||||
|
|
||||||
|
|
||||||
|
def hashPassword(password: str) -> str:
|
||||||
|
"""
|
||||||
|
Hash a password using Argon2.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
password: Plain text password to hash
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Hashed password string
|
||||||
|
"""
|
||||||
|
return _pwdContext.hash(password)
|
||||||
|
|
||||||
|
|
||||||
|
def verifyPassword(plainPassword: str, hashedPassword: str) -> bool:
|
||||||
|
"""
|
||||||
|
Verify a plain password against a hashed password.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
plainPassword: Plain text password to verify
|
||||||
|
hashedPassword: Hashed password to compare against
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if password matches, False otherwise
|
||||||
|
"""
|
||||||
|
return _pwdContext.verify(plainPassword, hashedPassword)
|
||||||
|
|
||||||
|
|
||||||
|
def getPasswordHash(password: Optional[str]) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Hash a password, returning None if password is None.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
password: Plain text password or None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Hashed password or None if input was None
|
||||||
|
"""
|
||||||
|
if password is None:
|
||||||
|
return None
|
||||||
|
return _pwdContext.hash(password)
|
||||||
|
|
@ -19,7 +19,7 @@ import logging
|
||||||
from modules.datamodels.datamodelUam import User
|
from modules.datamodels.datamodelUam import User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatWorkflow
|
from modules.aichat.datamodelFeatureAiChat import ChatWorkflow
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from modules.datamodels.datamodelUam import User, UserConnection
|
from modules.datamodels.datamodelUam import User, UserConnection
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatDocument, ChatMessage, ChatStat, ChatLog
|
from modules.aichat.datamodelFeatureAiChat import ChatDocument, ChatMessage, ChatStat, ChatLog
|
||||||
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
||||||
from modules.shared.progressLogger import ProgressLogger
|
from modules.shared.progressLogger import ProgressLogger
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ class UtilsService:
|
||||||
Mirrors storeDebugMessageAndDocuments() in modules.interfaces.interfaceDbChat.
|
Mirrors storeDebugMessageAndDocuments() in modules.interfaces.interfaceDbChat.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from modules.features.aichat.interfaceFeatureAiChat import storeDebugMessageAndDocuments as _storeDebugMessageAndDocuments
|
from modules.aichat.interfaceFeatureAiChat import storeDebugMessageAndDocuments as _storeDebugMessageAndDocuments
|
||||||
_storeDebugMessageAndDocuments(message, currentUser)
|
_storeDebugMessageAndDocuments(message, currentUser)
|
||||||
except Exception:
|
except Exception:
|
||||||
# Silent fail to never break main flow
|
# Silent fail to never break main flow
|
||||||
|
|
|
||||||
19
modules/shared/__init__.py
Normal file
19
modules/shared/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Copyright (c) 2025 Patrick Motsch
|
||||||
|
# All rights reserved.
|
||||||
|
"""
|
||||||
|
Shared utilities module.
|
||||||
|
Contains common utilities used across the gateway application.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from . import jsonUtils
|
||||||
|
from . import timeUtils
|
||||||
|
from . import attributeUtils
|
||||||
|
from . import frontendTypes
|
||||||
|
from . import configuration
|
||||||
|
from . import eventManagement
|
||||||
|
from . import auditLogger
|
||||||
|
from . import debugLogger
|
||||||
|
from . import progressLogger
|
||||||
|
from . import callbackRegistry
|
||||||
|
from . import jsonContinuation
|
||||||
|
from . import dbMultiTenantOptimizations
|
||||||
|
|
@ -12,7 +12,7 @@ import logging
|
||||||
import json
|
import json
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum, AutomationDefinition
|
from modules.aichat.datamodelFeatureAiChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum, AutomationDefinition
|
||||||
from modules.datamodels.datamodelUam import User
|
from modules.datamodels.datamodelUam import User
|
||||||
from modules.shared.timeUtils import getUtcTimestamp
|
from modules.shared.timeUtils import getUtcTimestamp
|
||||||
from modules.shared.eventManagement import eventManager
|
from modules.shared.eventManagement import eventManager
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ActionResult
|
from modules.aichat.datamodelFeatureAiChat import ActionResult
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Dict, Any, Optional, List
|
from typing import Dict, Any, Optional, List
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument
|
from modules.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument
|
||||||
from modules.datamodels.datamodelExtraction import ContentPart
|
from modules.datamodels.datamodelExtraction import ContentPart
|
||||||
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
||||||
from modules.datamodels.datamodelWorkflow import AiResponse, DocumentData
|
from modules.datamodels.datamodelWorkflow import AiResponse, DocumentData
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Dict, Any, Optional, List
|
from typing import Dict, Any, Optional, List
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument
|
from modules.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument
|
||||||
from modules.datamodels.datamodelExtraction import ContentPart
|
from modules.datamodels.datamodelExtraction import ContentPart
|
||||||
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
|
||||||
from modules.datamodels.datamodelWorkflow import AiResponse, DocumentData
|
from modules.datamodels.datamodelWorkflow import AiResponse, DocumentData
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import logging
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument
|
from modules.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument
|
||||||
from modules.datamodels.datamodelAi import AiCallOptions
|
from modules.datamodels.datamodelAi import AiCallOptions
|
||||||
from modules.datamodels.datamodelExtraction import ContentPart
|
from modules.datamodels.datamodelExtraction import ContentPart
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from modules.features.aichat.datamodelFeatureAiChat import ActionResult
|
from modules.aichat.datamodelFeatureAiChat import ActionResult
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue