refactored pages ui access with saas mandates

This commit is contained in:
ValueOn AG 2026-01-23 21:05:47 +01:00
parent f45cf79474
commit 6187cc7295
8 changed files with 168 additions and 131 deletions

View file

@ -10,7 +10,6 @@ Usage examples:
from . import datamodelAi as ai from . import datamodelAi as ai
from . import datamodelUam as uam from . import datamodelUam as uam
from . import datamodelSecurity as security from . import datamodelSecurity as security
from . import datamodelNeutralizer as neutralizer
from . import datamodelChat as chat from . import datamodelChat as chat
from . import datamodelFiles as files from . import datamodelFiles as files
from . import datamodelVoice as voice from . import datamodelVoice as voice

View file

@ -154,13 +154,28 @@ async def getRoleOptions(
async def getContractOptions( async def getContractOptions(
request: Request, request: Request,
instanceId: str = Path(..., description="Feature Instance ID"), instanceId: str = Path(..., description="Feature Instance ID"),
organisationId: Optional[str] = Query(None, description="Optional: Filter by organisation ID"),
context: RequestContext = Depends(getRequestContext) context: RequestContext = Depends(getRequestContext)
) -> List[Dict[str, Any]]: ) -> List[Dict[str, Any]]:
"""Get contract options for select dropdowns. Returns: [{ value, label }]""" """
Get contract options for select dropdowns.
Optionally filter by organisationId to get only contracts for a specific organisation.
This is useful for dependent dropdowns in forms.
Returns: [{ value, label }]
"""
mandateId = await _validateInstanceAccess(instanceId, context) mandateId = await _validateInstanceAccess(instanceId, context)
interface = getInterface(context.user, mandateId=mandateId, featureInstanceId=instanceId) interface = getInterface(context.user, mandateId=mandateId, featureInstanceId=instanceId)
result = interface.getAllContracts(None)
items = result.items if hasattr(result, 'items') else result if organisationId:
# Gefiltert nach Organisation
items = interface.getContractsByOrganisation(organisationId)
else:
# Alle Contracts
result = interface.getAllContracts(None)
items = result.items if hasattr(result, 'items') else result
return [{"value": c.id, "label": c.label or c.name or c.id} for c in items] return [{"value": c.id, "label": c.label or c.name or c.id} for c in items]
@ -176,7 +191,7 @@ async def getDocumentOptions(
interface = getInterface(context.user, mandateId=mandateId, featureInstanceId=instanceId) interface = getInterface(context.user, mandateId=mandateId, featureInstanceId=instanceId)
result = interface.getAllDocuments(None) result = interface.getAllDocuments(None)
items = result.items if hasattr(result, 'items') else result items = result.items if hasattr(result, 'items') else result
return [{"value": d.id, "label": d.name or d.id} for d in items] return [{"value": d.id, "label": d.documentName or d.id} for d in items]
@router.get("/{instanceId}/positions/options", response_model=List[Dict[str, Any]]) @router.get("/{instanceId}/positions/options", response_model=List[Dict[str, Any]])
@ -191,7 +206,17 @@ async def getPositionOptions(
interface = getInterface(context.user, mandateId=mandateId, featureInstanceId=instanceId) interface = getInterface(context.user, mandateId=mandateId, featureInstanceId=instanceId)
result = interface.getAllPositions(None) result = interface.getAllPositions(None)
items = result.items if hasattr(result, 'items') else result items = result.items if hasattr(result, 'items') else result
return [{"value": p.id, "label": p.title or p.id} for p in items] # Erstelle Label aus Datum, Firma und Beschreibung
def _makePositionLabel(p):
parts = []
if p.valuta:
parts.append(str(p.valuta)[:10]) # Datum ohne Zeit
if p.company:
parts.append(p.company[:30])
if p.desc:
parts.append(p.desc[:30])
return " - ".join(parts) if parts else p.id
return [{"value": p.id, "label": _makePositionLabel(p)} for p in items]
# ============================================================================ # ============================================================================

View file

@ -17,7 +17,7 @@ import logging
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from modules.auth import limiter, getRequestContext, RequestContext, requireSysAdmin from modules.auth import limiter, getRequestContext, RequestContext, requireSysAdmin
from modules.datamodels.datamodelUam import User from modules.datamodels.datamodelUam import User, UserInDB
from modules.datamodels.datamodelFeatures import Feature, FeatureInstance from modules.datamodels.datamodelFeatures import Feature, FeatureInstance
from modules.interfaces.interfaceDbApp import getRootInterface from modules.interfaces.interfaceDbApp import getRootInterface
from modules.interfaces.interfaceFeatures import getFeatureInterface from modules.interfaces.interfaceFeatures import getFeatureInterface

View file

@ -13,7 +13,7 @@ from fastapi import APIRouter, HTTPException, Depends, Body, Path, Query, Reques
from modules.auth import limiter, getRequestContext, RequestContext from modules.auth import limiter, getRequestContext, RequestContext
# Import interfaces # Import interfaces
from . import interfaceFeatureAiChat as interfaceDbChat from modules.interfaces import interfaceDbChat
# Import models # Import models
from modules.datamodels.datamodelChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum from modules.datamodels.datamodelChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum

View file

@ -17,7 +17,7 @@ from jose import jwt
from modules.auth import getCurrentUser, limiter, SECRET_KEY, ALGORITHM from modules.auth import getCurrentUser, limiter, SECRET_KEY, ALGORITHM
from modules.auth import createAccessToken, createRefreshToken, setAccessTokenCookie, setRefreshTokenCookie, clearAccessTokenCookie, clearRefreshTokenCookie from modules.auth import createAccessToken, createRefreshToken, setAccessTokenCookie, setRefreshTokenCookie, clearAccessTokenCookie, clearRefreshTokenCookie
from modules.interfaces.interfaceDbApp import getInterface, getRootInterface from modules.interfaces.interfaceDbApp import getInterface, getRootInterface
from modules.datamodels.datamodelUam import User, UserInDB, AuthAuthority from modules.datamodels.datamodelUam import User, UserInDB, AuthAuthority, Mandate
from modules.datamodels.datamodelSecurity import Token from modules.datamodels.datamodelSecurity import Token
from modules.shared.configuration import APP_CONFIG from modules.shared.configuration import APP_CONFIG

View file

@ -5,7 +5,6 @@ import logging
import re import re
from typing import Any, Dict, List, Optional, Tuple, Union, Type, TypeVar from typing import Any, Dict, List, Optional, Tuple, Union, Type, TypeVar
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError
from modules.datamodels.datamodelAi import ContinuationContext
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -867,7 +866,7 @@ def buildContinuationContext(
lastRawResponse: Optional[str] = None, lastRawResponse: Optional[str] = None,
useCaseId: Optional[str] = None, useCaseId: Optional[str] = None,
templateStructure: Optional[str] = None templateStructure: Optional[str] = None
) -> ContinuationContext: ) -> "ContinuationContext":
""" """
Build context information from accumulated sections for continuation prompt. Build context information from accumulated sections for continuation prompt.
@ -882,6 +881,8 @@ def buildContinuationContext(
Returns: Returns:
ContinuationContext: Pydantic model with all continuation context information ContinuationContext: Pydantic model with all continuation context information
""" """
# Lazy import to avoid circular dependency
from modules.datamodels.datamodelAi import ContinuationContext
section_count = len(allSections) section_count = len(allSections)
# Build summary of delivered data (per-section counts) # Build summary of delivered data (per-section counts)

View file

@ -2,10 +2,10 @@
FUNCTION IMPORTS ANALYSIS FUNCTION IMPORTS ANALYSIS
================================================================================ ================================================================================
Total function imports (internal modules): 226 Total function imports (internal modules): 229
- CIRCULAR (must stay): 4 - CIRCULAR (must stay): 4
- REDUNDANT (can remove): 0 - REDUNDANT (can remove): 0
- MOVABLE (can move): 222 - MOVABLE (can move): 225
================================================================================ ================================================================================
@ -17,121 +17,6 @@ gateway.app
----------- -----------
[lifespan] modules.shared.auditLogger [lifespan] modules.shared.auditLogger
gateway.modules.aichat.datamodelFeatureAiChat
---------------------------------------------
[updateFromSelection] modules.datamodels.datamodelWorkflow
gateway.modules.aichat.interfaceFeatureAiChat
---------------------------------------------
[_enrichAutomationsWithUserAndMandate] modules.interfaces.interfaceDbApp
[storeDebugMessageAndDocuments] modules.interfaces.interfaceDbManagement
[setUserContext] modules.security.rootAccess
[_notifyAutomationChanged] modules.shared.callbackRegistry
[storeDebugMessageAndDocuments] modules.shared.debugLogger
gateway.modules.aichat.serviceAi.mainServiceAi
----------------------------------------------
[renderResult] modules.aichat.serviceGeneration.mainServiceGeneration
[_handleCodeGeneration] modules.aichat.serviceGeneration.paths.codePath
[_handleDocumentGeneration] modules.aichat.serviceGeneration.paths.documentPath
[_handleImageGeneration] modules.aichat.serviceGeneration.paths.imagePath
gateway.modules.aichat.serviceAi.subContentExtraction
-----------------------------------------------------
[extractTextFromImage] modules.datamodels.datamodelAi
[processTextContentWithAi] modules.datamodels.datamodelAi
gateway.modules.aichat.serviceAi.subJsonResponseHandling
--------------------------------------------------------
[mergeFragmentIntoSection] modules.shared.debugLogger
gateway.modules.aichat.serviceAi.subStructureFilling
----------------------------------------------------
[_getAcceptedSectionTypesForFormat] modules.aichat.serviceGeneration.renderers.registry
[_getAcceptedSectionTypesForFormat] modules.datamodels.datamodelJson
[buildSectionPromptWithContinuation] modules.shared.jsonContinuation
[_extractAndMergeMultipleJsonBlocks] modules.shared.jsonUtils
[_processAiResponseForSection] modules.shared.jsonUtils
[_processSingleSection] modules.shared.jsonUtils
gateway.modules.aichat.serviceAi.subStructureGeneration
-------------------------------------------------------
[generateStructure] modules.aichat.serviceGeneration.renderers.registry
[generateStructure] modules.shared
[generateStructure] modules.shared.jsonContinuation
gateway.modules.aichat.serviceExtraction.mainServiceExtraction
--------------------------------------------------------------
[extractContent] modules.interfaces.interfaceDbManagement
[extractContent] modules.shared.debugLogger
gateway.modules.aichat.serviceExtraction.subPromptBuilderExtraction
-------------------------------------------------------------------
[buildExtractionPrompt] modules.shared.debugLogger
gateway.modules.aichat.serviceGeneration.mainServiceGeneration
--------------------------------------------------------------
[getAdaptiveExtractionPrompt] modules.aichat.serviceExtraction.subPromptBuilderExtraction
[renderReport] modules.aichat.serviceGeneration.renderers.registry
[generateDocumentWithTwoPhases] modules.aichat.serviceGeneration.subContentGenerator
[generateDocumentWithTwoPhases] modules.aichat.serviceGeneration.subStructureGenerator
gateway.modules.aichat.serviceGeneration.paths.codePath
-------------------------------------------------------
[_getCodeRenderer] modules.aichat.serviceGeneration.renderers.registry
[generateCode] modules.datamodels.datamodelDocument
[_generateCodeStructure] modules.shared.jsonContinuation
[_generateSingleFileContent] modules.shared.jsonContinuation
gateway.modules.aichat.serviceGeneration.renderers.rendererDocx
---------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererHtml
---------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererImage
----------------------------------------------------------------
[_compressPromptWithAi] modules.datamodels.datamodelAi
[_generateAiImage] modules.datamodels.datamodelAi
gateway.modules.aichat.serviceGeneration.renderers.rendererJson
---------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererMarkdown
-------------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererPdf
--------------------------------------------------------------
[_getAiStylesWithPdfColors] modules.datamodels.datamodelAi
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererPptx
---------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererText
---------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.renderers.rendererXlsx
---------------------------------------------------------------
[_getAiStylesWithExcelColors] modules.datamodels.datamodelAi
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.aichat.serviceGeneration.subContentGenerator
------------------------------------------------------------
[_generateImageSection] modules.datamodels.datamodelAi
[_generateSimpleSection] modules.datamodels.datamodelAi
[_generateSimpleSection] modules.shared.jsonUtils
gateway.modules.aichat.serviceGeneration.subStructureGenerator
--------------------------------------------------------------
[generateStructure] modules.datamodels.datamodelAi
gateway.modules.auth.authentication gateway.modules.auth.authentication
----------------------------------- -----------------------------------
[requireSysAdmin] modules.shared.auditLogger [requireSysAdmin] modules.shared.auditLogger
@ -150,6 +35,14 @@ gateway.modules.auth.tokenRefreshService
[proactive_refresh] modules.security.rootAccess [proactive_refresh] modules.security.rootAccess
[refresh_expired_tokens] modules.security.rootAccess [refresh_expired_tokens] modules.security.rootAccess
gateway.modules.datamodels.datamodelChat
----------------------------------------
[updateFromSelection] modules.datamodels.datamodelWorkflow
gateway.modules.features.aichat.mainAiChat
------------------------------------------
[onStart] modules.aicore.aicoreModelRegistry
gateway.modules.features.automation.routeFeatureAutomation gateway.modules.features.automation.routeFeatureAutomation
---------------------------------------------------------- ----------------------------------------------------------
[execute_automation] modules.services [execute_automation] modules.services
@ -197,6 +90,14 @@ gateway.modules.interfaces.interfaceDbApp
----------------------------------------- -----------------------------------------
[getRootInterface] modules.security.rootAccess [getRootInterface] modules.security.rootAccess
gateway.modules.interfaces.interfaceDbChat
------------------------------------------
[_enrichAutomationsWithUserAndMandate] modules.interfaces.interfaceDbApp
[storeDebugMessageAndDocuments] modules.interfaces.interfaceDbManagement
[setUserContext] modules.security.rootAccess
[_notifyAutomationChanged] modules.shared.callbackRegistry
[storeDebugMessageAndDocuments] modules.shared.debugLogger
gateway.modules.interfaces.interfaceDbManagement gateway.modules.interfaces.interfaceDbManagement
------------------------------------------------ ------------------------------------------------
[_initializeStandardPrompts] modules.interfaces.interfaceDbApp [_initializeStandardPrompts] modules.interfaces.interfaceDbApp
@ -313,15 +214,123 @@ gateway.modules.security.rootAccess
gateway.modules.services.__init__ gateway.modules.services.__init__
--------------------------------- ---------------------------------
[__init__] modules.interfaces.interfaceDbApp [__init__] modules.interfaces.interfaceDbApp
[__init__] modules.interfaces.interfaceDbChat
[__init__] modules.interfaces.interfaceDbManagement [__init__] modules.interfaces.interfaceDbManagement
gateway.modules.services.serviceAi.mainAiChat
---------------------------------------------
[onStart] modules.aicore.aicoreModelRegistry
gateway.modules.services.serviceAi.mainServiceAi
------------------------------------------------
[renderResult] modules.services.serviceGeneration.mainServiceGeneration
[_handleCodeGeneration] modules.services.serviceGeneration.paths.codePath
[_handleDocumentGeneration] modules.services.serviceGeneration.paths.documentPath
[_handleImageGeneration] modules.services.serviceGeneration.paths.imagePath
gateway.modules.services.serviceAi.subContentExtraction
-------------------------------------------------------
[extractTextFromImage] modules.datamodels.datamodelAi
[processTextContentWithAi] modules.datamodels.datamodelAi
gateway.modules.services.serviceAi.subJsonResponseHandling
----------------------------------------------------------
[mergeFragmentIntoSection] modules.shared.debugLogger
gateway.modules.services.serviceAi.subStructureFilling
------------------------------------------------------
[_getAcceptedSectionTypesForFormat] modules.datamodels.datamodelJson
[_getAcceptedSectionTypesForFormat] modules.services.serviceGeneration.renderers.registry
[buildSectionPromptWithContinuation] modules.shared.jsonContinuation
[_extractAndMergeMultipleJsonBlocks] modules.shared.jsonUtils
[_processAiResponseForSection] modules.shared.jsonUtils
[_processSingleSection] modules.shared.jsonUtils
gateway.modules.services.serviceAi.subStructureGeneration
---------------------------------------------------------
[generateStructure] modules.services.serviceGeneration.renderers.registry
[generateStructure] modules.shared
[generateStructure] modules.shared.jsonContinuation
gateway.modules.services.serviceChat.mainServiceChat gateway.modules.services.serviceChat.mainServiceChat
---------------------------------------------------- ----------------------------------------------------
[getChatDocumentsFromDocumentList] modules.datamodels.datamodelDocref [getChatDocumentsFromDocumentList] modules.datamodels.datamodelDocref
gateway.modules.services.serviceExtraction.mainServiceExtraction
----------------------------------------------------------------
[extractContent] modules.interfaces.interfaceDbManagement
[extractContent] modules.shared.debugLogger
gateway.modules.services.serviceExtraction.subPromptBuilderExtraction
---------------------------------------------------------------------
[buildExtractionPrompt] modules.shared.debugLogger
gateway.modules.services.serviceGeneration.mainServiceGeneration
----------------------------------------------------------------
[getAdaptiveExtractionPrompt] modules.services.serviceExtraction.subPromptBuilderExtraction
[renderReport] modules.services.serviceGeneration.renderers.registry
[generateDocumentWithTwoPhases] modules.services.serviceGeneration.subContentGenerator
[generateDocumentWithTwoPhases] modules.services.serviceGeneration.subStructureGenerator
gateway.modules.services.serviceGeneration.paths.codePath
---------------------------------------------------------
[generateCode] modules.datamodels.datamodelDocument
[_getCodeRenderer] modules.services.serviceGeneration.renderers.registry
[_generateCodeStructure] modules.shared.jsonContinuation
[_generateSingleFileContent] modules.shared.jsonContinuation
gateway.modules.services.serviceGeneration.renderers.rendererDocx
-----------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererHtml
-----------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererImage
------------------------------------------------------------------
[_compressPromptWithAi] modules.datamodels.datamodelAi
[_generateAiImage] modules.datamodels.datamodelAi
gateway.modules.services.serviceGeneration.renderers.rendererJson
-----------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererMarkdown
---------------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererPdf
----------------------------------------------------------------
[_getAiStylesWithPdfColors] modules.datamodels.datamodelAi
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererPptx
-----------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererText
-----------------------------------------------------------------
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.renderers.rendererXlsx
-----------------------------------------------------------------
[_getAiStylesWithExcelColors] modules.datamodels.datamodelAi
[getAcceptedSectionTypes] modules.datamodels.datamodelJson
gateway.modules.services.serviceGeneration.subContentGenerator
--------------------------------------------------------------
[_generateImageSection] modules.datamodels.datamodelAi
[_generateSimpleSection] modules.datamodels.datamodelAi
[_generateSimpleSection] modules.shared.jsonUtils
gateway.modules.services.serviceGeneration.subStructureGenerator
----------------------------------------------------------------
[generateStructure] modules.datamodels.datamodelAi
gateway.modules.services.serviceUtils.mainServiceUtils gateway.modules.services.serviceUtils.mainServiceUtils
------------------------------------------------------ ------------------------------------------------------
[storeDebugMessageAndDocuments] modules.aichat.interfaceFeatureAiChat [storeDebugMessageAndDocuments] modules.interfaces.interfaceDbChat
[debugLogToFile] modules.shared.debugLogger [debugLogToFile] modules.shared.debugLogger
[writeDebugArtifact] modules.shared.debugLogger [writeDebugArtifact] modules.shared.debugLogger
[writeDebugFile] modules.shared.debugLogger [writeDebugFile] modules.shared.debugLogger
@ -409,9 +418,9 @@ gateway.modules.workflows.processing.modes.modeDynamic
gateway.modules.workflows.processing.shared.placeholderFactory gateway.modules.workflows.processing.shared.placeholderFactory
-------------------------------------------------------------- --------------------------------------------------------------
[extractReviewContent] modules.aichat.datamodelFeatureAiChat [extractReviewContent] modules.datamodels.datamodelChat
[extractLatestRefinementFeedback] modules.aichat.interfaceFeatureAiChat
[extractLatestRefinementFeedback] modules.interfaces.interfaceDbApp [extractLatestRefinementFeedback] modules.interfaces.interfaceDbApp
[extractLatestRefinementFeedback] modules.interfaces.interfaceDbChat
gateway.modules.workflows.workflowManager gateway.modules.workflows.workflowManager
----------------------------------------- -----------------------------------------

View file

@ -327,6 +327,9 @@ gateway.modules.datamodels.datamodelWorkflowActions,modules.shared.attributeUtil
gateway.modules.datamodels.datamodelWorkflowActions,modules.shared.frontendTypes,header,Yes gateway.modules.datamodels.datamodelWorkflowActions,modules.shared.frontendTypes,header,Yes
gateway.modules.datamodels.datamodelWorkflowActions,pydantic,header,Yes gateway.modules.datamodels.datamodelWorkflowActions,pydantic,header,Yes
gateway.modules.datamodels.datamodelWorkflowActions,typing,header,Yes gateway.modules.datamodels.datamodelWorkflowActions,typing,header,Yes
gateway.modules.features.aichat.mainAiChat,logging,header,Yes
gateway.modules.features.aichat.mainAiChat,modules.aicore.aicoreModelRegistry,function onStart,Yes
gateway.modules.features.aichat.mainAiChat,typing,header,Yes
gateway.modules.features.automation.datamodelFeatureAutomation,modules.shared.attributeUtils,header,Yes gateway.modules.features.automation.datamodelFeatureAutomation,modules.shared.attributeUtils,header,Yes
gateway.modules.features.automation.datamodelFeatureAutomation,pydantic,header,Yes gateway.modules.features.automation.datamodelFeatureAutomation,pydantic,header,Yes
gateway.modules.features.automation.datamodelFeatureAutomation,typing,header,Yes gateway.modules.features.automation.datamodelFeatureAutomation,typing,header,Yes

1 module_name imported_module_name position import_valid
327 gateway.modules.datamodels.datamodelWorkflowActions modules.shared.frontendTypes header Yes
328 gateway.modules.datamodels.datamodelWorkflowActions pydantic header Yes
329 gateway.modules.datamodels.datamodelWorkflowActions typing header Yes
330 gateway.modules.features.aichat.mainAiChat logging header Yes
331 gateway.modules.features.aichat.mainAiChat modules.aicore.aicoreModelRegistry function onStart Yes
332 gateway.modules.features.aichat.mainAiChat typing header Yes
333 gateway.modules.features.automation.datamodelFeatureAutomation modules.shared.attributeUtils header Yes
334 gateway.modules.features.automation.datamodelFeatureAutomation pydantic header Yes
335 gateway.modules.features.automation.datamodelFeatureAutomation typing header Yes