# Gateway: Doppelte Klassennamen bereinigen ## Beschreibung und Kontext Beim Aufräumen der `@i18nModel`-Migration (Phase 2) wurde festgestellt, dass mehrere Python-Klassen im Gateway **denselben Namen** tragen, obwohl sie in verschiedenen Modulen leben. Das ist problematisch, weil: 1. **i18n-Kollision:** `@i18nModel` registriert nach `cls.__name__` in einem globalen Dict — bei gleichem Namen überschreibt der letzte Import den ersten. 2. **Lesbarkeit:** Import-Aliase (`from ... import TaskResult as WorkflowTaskResult`) sind fragil und leicht vergessen. 3. **Tooling:** IDE-Suche, Debugging-Stacktraces und `getModelClasses()` liefern mehrdeutige Treffer. **Business-Treiber:** Saubere Klassennamen verhindern stille Label-Fehler in der UI und reduzieren Wartungsaufwand bei zukünftigen Erweiterungen. --- ## Vollständige Liste der Duplikate Ermittelt per AST-Scan über `gateway/modules/` (nur Klassen, die in **mehr als einer Datei** vorkommen): ### Kritisch: Pydantic-Modelle mit `@i18nModel` (i18n-Dict-Kollision) | Klassenname | Datei 1 | Datei 2 | Beschreibung | |-------------|---------|---------|--------------| | **`TaskResult`** | `datamodels/datamodelChat.py` | `datamodels/datamodelWorkflow.py` | Chat: Aufgabenergebnis mit Status/Feedback. Workflow: Minimales Ergebnis mit `actionResult`. Beide haben `@i18nModel("Aufgaben-Ergebnis")`. | | **`RequestContext`** | `datamodels/datamodelWorkflow.py` (Pydantic `BaseModel`) | `auth/authentication.py` (plain `class`) | Workflow: Normalisierter Benutzer-Input. Auth: Request-Kontext mit User/Mandate/Rollen. Kein i18n-Konflikt (Auth-Klasse ist kein Pydantic-Modell), aber Name ist irreführend. | ### Mittel: Lokale Hilfsklassen (kein i18n, aber verwirrend) | Klassenname | Datei 1 | Datei 2 | Beschreibung | |-------------|---------|---------|--------------| | **`AiResponse`** | `datamodels/datamodelWorkflow.py` (Pydantic) | `serviceAi/subStructureFilling.py` (inline `class` in try/except, 4×) | Workflow: Vollständiges AI-Antwort-Modell. StructureFiller: Minimaler Wrapper `AiResponse(content)` als Fallback bei Parse-Fehlern. | | **`TableData`** | `datamodels/datamodelDocument.py` (Pydantic) | `neutralization/.../subProcessList.py` (`@dataclass`) | Document: Strukturierte Tabelle mit Headers/Rows/Caption. Neutralization: Einfache Tabelle mit `source_type`. | | **`Token`** | `datamodels/datamodelSecurity.py` (Pydantic `PowerOnModel`) | `shared/jsonContinuation.py` (`@dataclass`) | Security: DB-Token (JWT, Refresh etc.). JsonContinuation: JSON-Parser-Token (internes Parsing). | ### Niedrig: Architektur-Helfer (domänengetrennt, kaum Verwechslungsgefahr) | Klassenname | Dateien | Beschreibung | |-------------|---------|--------------| | `ChatObjects` | `features/chatbot/interfaceFeatureChatbot.py`, `interfaces/interfaceDbChat.py` | Identische Rolle (Chat-Objekt-Container), ggf. zusammenführbar. | | `ConnectionHelper` | `workflows/methods/methodOutlook/helpers/connection.py`, `workflows/methods/methodSharepoint/helpers/connection.py` | Jeweils Outlook- bzw. SharePoint-spezifisch; Name ist generisch, aber Module sind klar getrennt. | | `DocumentParsingHelper` | `workflows/methods/methodJira/helpers/documentParsing.py`, `workflows/methods/methodSharepoint/helpers/documentParsing.py` | Jira- bzw. SharePoint-spezifisch; gleiche Situation wie `ConnectionHelper`. | | `StructureGenerator` | `serviceAi/subStructureGeneration.py`, `serviceGeneration/subStructureGenerator.py` | Zwei Services mit ähnlicher Aufgabe; ggf. Konsolidierung prüfen. | | `_ResolverDbAdapter` | `features/graphicalEditor/routeFeatureGraphicalEditor.py`, `features/workspace/routeFeatureWorkspace.py` | Interner Adapter (`_`-Prefix); lebt nur im jeweiligen Route-Modul. | | `_ServicesAdapter` | 4× in `serviceCenter/services/*/main*.py` | Interner Adapter pro Service; bewusst gleichnamig, nie cross-importiert. | --- ## Lösungsvorschlag ### 1. `TaskResult` → Umbenennung (Priorität: hoch) **Problem:** Beide Klassen haben `@i18nModel("Aufgaben-Ergebnis")` — der letzte Import gewinnt im Label-Dict. **Lösung:** | Aktuell | Neu | Modul | |---------|-----|-------| | `TaskResult` in `datamodelChat.py` | **`ChatTaskResult`** | Chat-Domäne: Status, Feedback, Error | | `TaskResult` in `datamodelWorkflow.py` | **`WorkflowTaskResult`** | Workflow-Domäne: taskId + actionResult | **Betroffene Imports (5 Dateien):** - `workflows/processing/modes/modeBase.py` — importiert aus `datamodelChat` - `workflows/processing/modes/modeDynamic.py` — importiert aus `datamodelChat` - `workflows/processing/modes/modeAutomation.py` — importiert aus `datamodelChat` + `datamodelWorkflow` (bereits `as WorkflowTaskResult`) - `workflows/workflowManager.py` — importiert aus `datamodelWorkflow` (bereits `as WorkflowTaskResult`) - `workflows/processing/workflowProcessor.py` — importiert aus `datamodelWorkflow` - `tests/unit/datamodels/test_workflow_models.py` — importiert aus `datamodelWorkflow` **i18n-Labels anpassen:** - `ChatTaskResult`: `@i18nModel("Chat-Aufgabenergebnis")` - `WorkflowTaskResult`: `@i18nModel("Workflow-Aufgabenergebnis")` **Aufwand:** Klein (6 Dateien, reine Umbenennung + Import-Anpassung). ### 2. `AiResponse` in `subStructureFilling.py` → Inline-Klasse eliminieren (Priorität: mittel) **Problem:** 4× identische `class AiResponse` inline in try/except-Blöcken als Fallback-Wrapper. **Lösung:** Eine private Klasse `_AiResponseFallback` am Modulanfang definieren, die 4 Inline-Definitionen ersetzen. ```python @dataclass class _AiResponseFallback: content: Any ``` **Aufwand:** Klein (1 Datei, 4 Stellen). ### 3. `TableData` in `subProcessList.py` → Umbenennen (Priorität: mittel) **Lösung:** `TableData` in `subProcessList.py` → **`NeutralizationTableData`** (oder `_ParsedTableData`). Wird nur modulintern verwendet. **Aufwand:** Minimal (1 Datei). ### 4. `Token` in `jsonContinuation.py` → Umbenennen (Priorität: niedrig) **Lösung:** `Token` → **`JsonToken`** (passend zu `TokenType` → `JsonTokenType`). Wird nur modulintern verwendet. **Aufwand:** Minimal (1 Datei, rein intern). ### 5. `RequestContext` — Kein Handlungsbedarf Die Auth-`RequestContext` ist kein Pydantic-Modell und hat kein `@i18nModel`. Die Workflow-`RequestContext` ist ein Pydantic-Modell mit `@i18nModel`. Es gibt **keine Import-Überschneidung** (Auth wird nie aus `datamodelWorkflow` importiert und umgekehrt). Kein Refactoring nötig. ### 6. Niedrige Kategorie — Kein Handlungsbedarf `ChatObjects`, `ConnectionHelper`, `DocumentParsingHelper`, `StructureGenerator`, `_ResolverDbAdapter`, `_ServicesAdapter` leben in klar getrennten Domänen und werden nie cross-importiert. Umbenennung wäre kosmetisch. --- ## Umsetzungsreihenfolge | Schritt | Was | Dateien | Aufwand | |---------|-----|---------|---------| | 1 | `TaskResult` → `ChatTaskResult` / `WorkflowTaskResult` | 8 | 30 min | | 2 | Inline `AiResponse` → `_AiResponseFallback` | 1 | 10 min | | 3 | `TableData` → `NeutralizationTableData` | 1 | 5 min | | 4 | `Token` → `JsonToken` | 1 | 5 min | **Gesamtaufwand:** ~50 min, kein Risiko für Laufzeitverhalten (reine Umbenennungen). --- ## Validierung - `python -c "import app"` muss fehlerfrei durchlaufen - Bestehende Tests (`tests/unit/datamodels/test_workflow_models.py`) anpassen und grün halten - `getModelAttributeDefinitions` für betroffene Modelle prüfen (Labels eindeutig)