594 lines
27 KiB
Markdown
594 lines
27 KiB
Markdown
# Konzept: Agent Toolbox & Dateisystem-Erweiterung
|
|
|
|
> Poweron Platform -- Erweiterung der Agent-Fähigkeiten und des Dateisystems
|
|
> Status: Konzept / Version 1.2 / März 2026
|
|
|
|
---
|
|
|
|
## 1. Ausgangslage (IST-Zustand)
|
|
|
|
### 1.1 Datenmodelle
|
|
|
|
Die Grundstruktur für ein hierarchisches Dateisystem existiert bereits, wird aber kaum genutzt.
|
|
|
|
**FileItem** (`gateway/modules/datamodels/datamodelFiles.py`):
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `id` | str | Primary Key (UUID) |
|
|
| `fileName` | str | Dateiname |
|
|
| `mimeType` | str | MIME-Typ |
|
|
| `fileSize` | int | Grösse in Bytes |
|
|
| `folderId` | Optional[str] | Verweis auf übergeordneten Folder |
|
|
| `featureInstanceId` | Optional[str] | Feature-Instanz-Zuordnung |
|
|
| `tags` | Optional[List[str]] | Tags |
|
|
| `status` | Optional[str] | Verarbeitungsstatus |
|
|
| `description` | Optional[str] | Beschreibung |
|
|
|
|
**FileFolder** (`gateway/modules/datamodels/datamodelFileFolder.py`):
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `id` | str | Primary Key (UUID) |
|
|
| `name` | str | Ordnername |
|
|
| `parentId` | Optional[str] | Übergeordneter Folder (None = Root) |
|
|
| `mandateId` | Optional[str] | Mandant |
|
|
| `featureInstanceId` | Optional[str] | Feature-Instanz-Zuordnung |
|
|
|
|
### 1.2 Backend-Operationen
|
|
|
|
```
|
|
Vorhanden Fehlend
|
|
───────────────────── ──────────────────────
|
|
Files: Files:
|
|
createFile ✓ copyFile ✗
|
|
deleteFile ✓
|
|
updateFile ✓ (Metadaten)
|
|
createFileData ✓ (Update-Pfad: Logik aus Codeeditor applyEdit kopieren)
|
|
getAllFiles ✓
|
|
|
|
Folders: Folders:
|
|
createFolder ✓ deleteFolder ✗
|
|
listFolders ✓ renameFolder ✗
|
|
moveFolder ✗
|
|
getFolder ✗
|
|
```
|
|
|
|
### 1.3 Agent-Tools (27 registriert)
|
|
|
|
Dateibezogene Tools im aktuellen Agent:
|
|
|
|
| Tool | Funktion | Status |
|
|
|------|----------|--------|
|
|
| `readFile` | Datei lesen | Vorhanden |
|
|
| `listFiles` | Dateien auflisten | Vorhanden |
|
|
| `searchFiles` | Dateien suchen | Vorhanden |
|
|
| `writeFile` | Neue Datei erstellen | Vorhanden |
|
|
| `moveFile` | Datei verschieben (via `updateFile({folderId})`) | Vorhanden |
|
|
| `tagFile` | Tags setzen | Vorhanden |
|
|
| `createFolder` | Ordner erstellen | Vorhanden |
|
|
| `listFolders` | Ordner auflisten | Vorhanden |
|
|
| `deleteFile` | Datei löschen | **Fehlt** (Backend existiert) |
|
|
| `renameFile` | Datei umbenennen | **Fehlt** (Backend existiert) |
|
|
| `editFile` | Dateiinhalt ändern | **Fehlt** (Logik aus Codeeditor `applyEdit` extrahieren) |
|
|
| `copyFile` | Datei duplizieren | **Fehlt** (Backend muss gebaut werden) |
|
|
|
|
### 1.4 Codeeditor-Feature (wird entfernt -- Logik extrahieren)
|
|
|
|
Das bestehende **Codeeditor-Feature** (`gateway/modules/features/codeeditor/`) wird perspektivisch entfernt. Es enthält jedoch bewährte File-Edit-Logik, die vor dem Entfernen in den Workspace-Agent **kopiert** werden muss:
|
|
|
|
**Zu extrahierende Backend-Logik:**
|
|
|
|
| Datei | Was kopieren |
|
|
|-------|-------------|
|
|
| `routeFeatureCodeeditor.py` | `applyEdit()`-Logik: File-Write via `createFileData(fileId, contentBytes)`, MIME-Type-Erkennung |
|
|
| `datamodelCodeeditor.py` | `FileEditProposal`, `EditStatusEnum` (PENDING → ACCEPTED / REJECTED) |
|
|
| `responseParser.py` | `file_edit`-Block-Parsing (`fileName`, `oldContent`, `newContent`) |
|
|
|
|
**Zu extrahierende Frontend-Logik:**
|
|
|
|
| Datei | Was kopieren |
|
|
|-------|-------------|
|
|
| `DiffPreviewPanel.tsx` | Diff-View mit Accept/Reject-Buttons → als Shared-Komponente extrahieren |
|
|
| `useCodeEditor.ts` | `acceptEdit` / `rejectEdit` Handlers → in Workspace-Hook übernehmen |
|
|
|
|
### 1.5 Frontend
|
|
|
|
- **FileBrowser** (`frontend_nyla/src/pages/views/workspace/FileBrowser.tsx`): Gruppiert Dateien nach `featureInstanceId`, ignoriert `folderId` und Folder komplett. Kein Folder-Tree.
|
|
- **FilesPage** (`frontend_nyla/src/pages/basedata/FilesPage.tsx`): Flache Tabelle mit FormGeneratorTable. Keine Ordner-Navigation.
|
|
- **DataSourcePanel**: Externer Datenquellen-Tree existiert als Referenzimplementierung für Lazy-Loading-Tree-UI.
|
|
|
|
---
|
|
|
|
## 2. Dateisystem-Erweiterung (Backend)
|
|
|
|
### 2.1 Übersicht
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph fileSystem [Hierarchisches Dateisystem]
|
|
Root["(Global) Root"]
|
|
FolderA["Folder: Projekte"]
|
|
FolderB["Folder: Analysen"]
|
|
FolderC["Folder: Q1"]
|
|
FileA["File: Report.pdf"]
|
|
FileB["File: Daten.xlsx"]
|
|
FileC["File: Summary.md"]
|
|
Root --> FolderA
|
|
Root --> FolderB
|
|
FolderA --> FolderC
|
|
FolderA --> FileA
|
|
FolderC --> FileB
|
|
FolderB --> FileC
|
|
end
|
|
|
|
subgraph agent [Agent Tools]
|
|
CRUD_Files["Files: create, read, edit, copy, delete, rename, move"]
|
|
CRUD_Folders["Folders: create, delete, rename, move, list"]
|
|
end
|
|
|
|
agent -->|"operiert auf"| fileSystem
|
|
```
|
|
|
|
### 2.2 Neue/Erweiterte DB-Methoden
|
|
|
|
Alle Methoden in `interfaceDbManagement.py` ergänzen:
|
|
|
|
**Übergreifende Regeln für alle Folder-Operationen:**
|
|
- **Unique-Name-Constraint:** Innerhalb eines Folders darf ein Foldername nur einmal vorkommen (unique pro `parentId`)
|
|
- **Geschützter Name:** Der Name `"(Global)"` ist reserviert für den virtuellen Root und darf nicht für echte Folder verwendet werden
|
|
- Validation bei `createFolder`, `renameFolder`, `moveFolder`
|
|
|
|
**deleteFolder(folderId, recursive=False)**
|
|
- Wenn `recursive=True`: Alle Dateien und Unterordner kaskadierend löschen
|
|
- Wenn `recursive=False` und Folder nicht leer: Fehler werfen
|
|
- RBAC-Check auf Folder-Ebene
|
|
|
|
**renameFolder(folderId, newName)**
|
|
- Via `recordModify(FileFolder, folderId, {"name": newName})`
|
|
- **Unique-Name-Constraint:** Prüfen, dass im gleichen `parentId` kein anderer Folder mit `newName` existiert
|
|
- **Geschützter Name:** `"(Global)"` darf nicht als Foldername verwendet werden (reserviert für virtuellen Root)
|
|
|
|
**moveFolder(folderId, targetParentId)**
|
|
- Validierung: Zirkelverweis verhindern (Folder darf nicht in eigenen Unterbaum verschoben werden)
|
|
- **Unique-Name-Constraint:** Prüfen, dass im Ziel-Folder kein Folder mit gleichem Namen existiert
|
|
- Via `recordModify(FileFolder, folderId, {"parentId": targetParentId})`
|
|
|
|
**copyFile(sourceFileId, targetFolderId=None, newFileName=None)**
|
|
- FileItem duplizieren mit neuer ID
|
|
- **FileData vollständig duplizieren** (eigenständige Kopie, damit die Kopie unabhängig bearbeitet werden kann)
|
|
- Optional: neuer Name, anderer Ziel-Folder
|
|
|
|
**updateFileData(fileId, data)** -- Logik aus Codeeditor `applyEdit` kopieren
|
|
- `createFileData(fileId, contentBytes)` zum Überschreiben bestehender Dateien
|
|
- Falls `createFileData` bei existierenden Daten überspringt: vorher `deleteFileData(fileId)`, dann `createFileData(fileId, newData)`
|
|
- FileItem-Metadaten aktualisieren (fileSize, fileHash via `updateFile`)
|
|
- Hinweis: Codeeditor wird später entfernt -- relevante Logik vorher in `interfaceDbManagement` oder Agent-Tool extrahieren
|
|
|
|
### 2.3 Root-Folder "(Global)"
|
|
|
|
Der Root-Folder ist **virtuell** und wird nicht als DB-Eintrag gespeichert:
|
|
- Dateien mit `folderId=None` gehören zum Root
|
|
- Ordner mit `parentId=None` sind Top-Level-Ordner unter Root
|
|
- Anzeige im UI als "(Global)" Label
|
|
|
|
### 2.4 Migration: featureInstanceId entfernen
|
|
|
|
Die Gruppierung nach `featureInstanceId` wird durch die Ordnerstruktur ersetzt:
|
|
|
|
1. **Spalte beibehalten** aber nicht mehr für Gruppierung nutzen
|
|
2. `featureInstanceId` als informatives Metadatum ("Erstellt in: Workspace A") in einer zusätzlichen Tabellenspalte anzeigen
|
|
3. Bestehende Dateien: `folderId` bleibt `None` (Root), keine Migration nötig
|
|
4. Frontend-Gruppierung nach `featureInstanceId` entfernen, stattdessen Folder-Baum nutzen
|
|
|
|
---
|
|
|
|
## 3. Neue Agent-Tools
|
|
|
|
### 3.1 Phase 1 -- Quick Wins (Backend existiert)
|
|
|
|
#### deleteFile
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `interfaceDbManagement.deleteFile(fileId)` |
|
|
| Parameter | `fileId` (required) |
|
|
| readOnly | false |
|
|
| Hinweis | Knowledge-Store-Einträge ebenfalls bereinigen |
|
|
|
|
#### renameFile
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `interfaceDbManagement.updateFile(fileId, {"fileName": newName})` |
|
|
| Parameter | `fileId` (required), `newName` (required) |
|
|
| readOnly | false |
|
|
|
|
#### readUrl
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `serviceWeb._performWebCrawl(urls=[url])` |
|
|
| Parameter | `url` (required) |
|
|
| readOnly | true |
|
|
| Hinweis | Ergänzt `webSearch`: Während `webSearch` nach Informationen sucht, liest `readUrl` gezielt eine bekannte URL |
|
|
|
|
#### translateText
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `interfaceVoiceObjects.translateText(text, targetLanguage)` + Google Cloud Translation |
|
|
| Parameter | `text` (required), `targetLanguage` (required), `sourceLanguage` (optional, auto-detect) |
|
|
| readOnly | true |
|
|
| Hinweis | Effizienter als AI-basierte Übersetzung für grosse Textmengen |
|
|
|
|
### 3.2 Phase 2 -- Dateisystem-Tools
|
|
|
|
#### deleteFolder
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | Neu: `interfaceDbManagement.deleteFolder()` |
|
|
| Parameter | `folderId` (required), `recursive` (optional, default false) |
|
|
| readOnly | false |
|
|
| Sicherheit | Agent muss vor kaskadierendem Löschen bestätigen (Anzahl betroffener Dateien nennen) |
|
|
|
|
#### renameFolder
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | Neu: `interfaceDbManagement.renameFolder()` |
|
|
| Parameter | `folderId` (required), `newName` (required) |
|
|
| readOnly | false |
|
|
|
|
#### moveFolder
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | Neu: `interfaceDbManagement.moveFolder()` |
|
|
| Parameter | `folderId` (required), `targetParentId` (required, null für Root) |
|
|
| readOnly | false |
|
|
| Validierung | Zirkelverweis-Check: Ziel darf kein Unterordner der Quelle sein |
|
|
|
|
#### copyFile
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | Neu: `interfaceDbManagement.copyFile()` |
|
|
| Parameter | `fileId` (required), `targetFolderId` (optional), `newFileName` (optional) |
|
|
| readOnly | false |
|
|
| Implementierung | Vollständige Duplikation: FileItem + FileData werden als eigenständige Kopie erstellt (editierbar) |
|
|
|
|
#### editFile
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `dbManagement.createFileData(fileId, contentBytes)` (Logik aus Codeeditor kopiert, siehe 5.2) |
|
|
| Parameter | `fileId` (required), `content` (required, Text-Inhalt) |
|
|
| readOnly | false |
|
|
| Einschränkung | Nur für Text-basierte Dateien (text/\*, application/json, etc.) |
|
|
| UX-Option | Optional: Approve/Reject-Mode (Agent schlägt Edit als Diff vor, User bestätigt) |
|
|
|
|
### 3.3 Phase 3 -- Erweiterte Fähigkeiten
|
|
|
|
#### speechToText
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `connectorVoiceGoogle.speechToText()` |
|
|
| Parameter | `fileId` (required, Audio-Datei), `language` (optional, auto-detect) |
|
|
| readOnly | true |
|
|
| Hinweis | Gegenstück zu `textToSpeech`. Akzeptiert Audio-Dateien aus dem Workspace |
|
|
|
|
#### detectLanguage
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `interfaceVoiceObjects.detectLanguage()` |
|
|
| Parameter | `text` (required) |
|
|
| readOnly | true |
|
|
|
|
#### searchImages
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | Neu: Google Custom Search API (Konzept in `local/pending/doc_enhancement_web_image_actions_pending.md`) |
|
|
| Parameter | `query` (required), `maxResults` (optional), `imageType` (optional), `size` (optional) |
|
|
| readOnly | true |
|
|
| Abhängigkeit | Google Custom Search API Key + Engine ID |
|
|
| Hinweis | Bilder werden als URLs zurückgegeben, können via `downloadFromDataSource` oder einem neuen Download-Mechanismus heruntergeladen werden |
|
|
|
|
#### neutralizeData
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | `serviceNeutralization.processText()` / `processFile()` |
|
|
| Parameter | `text` (optional) oder `fileId` (optional, eines von beiden required) |
|
|
| readOnly | true (gibt anonymisierten Text zurück, ändert Original nicht) |
|
|
|
|
#### executeCode
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| Backend | Neu: Sandboxed Code Execution |
|
|
| Parameter | `code` (required), `language` (required: "python" oder "javascript") |
|
|
| readOnly | true |
|
|
| Sicherheitskonzept | Siehe Abschnitt 5.1 |
|
|
|
|
---
|
|
|
|
## 4. UI-Umbau
|
|
|
|
### 4.1 Dateien-Seite (Split-View)
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────┐
|
|
│ Dateien │
|
|
├───────────────────┬──────────────────────────────────────┤
|
|
│ │ [+ Upload / Drag&Drop] [Filter]│
|
|
│ (Global) │ ─────────────────────────────────── │
|
|
│ ├── Projekte │ Name Typ Grösse Quelle │
|
|
│ │ ├── Q1 │ ─────────────────────────────────── │
|
|
│ │ └── Q2 │ Report.pdf PDF 1.2 MB Workspace│
|
|
│ ├── Analysen │ Daten.xlsx XLSX 450 KB Chat AI │
|
|
│ └── Archiv │ Notes.md MD 12 KB Chat AI │
|
|
│ │ │
|
|
│ [+ Neuer Ordner] │ │
|
|
│ │ │
|
|
├───────────────────┴──────────────────────────────────────┤
|
|
│ ◄═══════════════ Divider (verschiebbar) ═══════════════►│
|
|
└──────────────────────────────────────────────────────────┘
|
|
|
|
Wichtig: Die Action-Buttons (Upload, Filter) sind OBERHALB der Tabelle fixiert,
|
|
damit sie bei wechselnder Tabellengrösse nicht springen.
|
|
```
|
|
|
|
### 4.2 Komponenten
|
|
|
|
**FolderTree (neue Shared-Komponente)**
|
|
- Rekursiv verschachtelbarer Baum
|
|
- Lazy-Loading der Unterordner (Referenz: `DataSourcePanel.tsx` für Tree-Pattern)
|
|
- **Inline-Icons pro Folder-Zeile:** Delete (🗑), Add Subfolder (+), Rename (✏) -- direkt sichtbar, kein Kontextmenü nötig
|
|
- **Drag-and-Drop:** Folders und Files können per Drag auf andere Folders verschoben werden
|
|
- Visuelles Feedback: Drop-Target-Highlighting beim Hover über gültiges Ziel
|
|
- Wiederverwendbar in der Dateien-Seite UND im Workspace-Chat (gleiche Komponente)
|
|
|
|
**FileTable (bestehend, erweitert)**
|
|
- Zeigt Dateien des aktuell markierten Folders
|
|
- Neue Spalte "Quelle" (zeigt `featureInstanceLabel` als Information, nicht als Gruppierung)
|
|
- **Drag-and-Drop:** Dateien aus der Tabelle in den Folder-Tree ziehen zum Verschieben
|
|
- Kontextmenü pro Datei: Umbenennen, Löschen, Kopieren, Verschieben, Download
|
|
|
|
**SplitView / Divider**
|
|
- Verschiebbar per Maus-Drag
|
|
- Default-Position: 25% links / 75% rechts
|
|
- Minimum-Breite pro Seite: 200px
|
|
- Position persistent im LocalStorage
|
|
|
|
### 4.3 Workspace-Integration
|
|
|
|
Im Workspace-Chat (`WorkspacePage.tsx`) wird der bestehende `FileBrowser` umgebaut:
|
|
- Statt Gruppierung nach `featureInstanceId`: der gleiche `FolderTree` wie auf der Dateien-Seite
|
|
- Kompaktere Darstellung (kein Split-View nötig, Tree + Dateien untereinander)
|
|
- Gleiche Drag-and-Drop-Fähigkeiten
|
|
|
|
---
|
|
|
|
## 5. Kritische Bewertung
|
|
|
|
### 5.1 executeCode -- Sicherheitskonzept
|
|
|
|
**Anforderung:** "Hier einfach nur für Analysen und Berechnungen zulassen, nicht für Codeelemente ausserhalb der Umgebung oder Installationen."
|
|
|
|
**Bewertung:** Sinnvoll und notwendig für Datenanalyse. Die Einschränkung auf Analysen/Berechnungen ist korrekt.
|
|
|
|
**Empfohlene Absicherung:**
|
|
- **Isolierte Ausführung:** RestrictedPython (Python) oder vm2/isolated-vm (JS) -- keine eigene Docker-Sandbox nötig für reine Berechnungen
|
|
- **Kein Dateisystem-Zugriff:** `open()`, `os`, `subprocess`, `sys` blockieren
|
|
- **Kein Netzwerk-Zugriff:** `socket`, `urllib`, `requests` blockieren
|
|
- **Keine Installationen:** `pip`, `import` nur für Whitelist (math, statistics, json, csv, re, datetime, collections, itertools, functools, decimal, fractions)
|
|
- **Timeout:** Max. 30 Sekunden Ausführungszeit
|
|
- **Memory-Limit:** Max. 256 MB
|
|
- **Output-Limit:** Max. 50.000 Zeichen Rückgabe
|
|
|
|
**Risiko-Bewertung:** Mittel. RestrictedPython ist gut getestet, aber kein perfekter Sandbox. Für den Use Case (Berechnungen, Datenanalyse) ist das Risiko vertretbar, solange die Whitelist strikt eingehalten wird.
|
|
|
|
### 5.2 editFile -- Logik aus Codeeditor übernehmen
|
|
|
|
**Anforderung:** "Bestehende Datei-Inhalte aktualisieren."
|
|
|
|
**Bewertung:** Das Codeeditor-Feature hat eine bewährte File-Edit-Pipeline (`applyEdit`-Route, `createFileData(fileId, contentBytes)`). Da der Codeeditor später entfernt wird, muss die benötigte Logik in den Workspace-Agent **kopiert** werden -- keine Referenzen auf Codeeditor-Module.
|
|
|
|
**Zu übernehmende Logik (aus Codeeditor extrahieren):**
|
|
- File-Write: `createFileData(fileId, contentBytes)` zum Überschreiben bestehender Dateien
|
|
- Falls `createFileData` bei existierenden Daten überspringt: `deleteFileData` → `createFileData` als Fallback
|
|
- MIME-Type-Erkennung: `_guessMimeType(fileName)` Logik kopieren
|
|
- FileItem-Metadaten (fileSize, fileHash) via `updateFile` aktualisieren
|
|
- MIME-Type-Check: Nur Text-basierte Dateien erlauben (text/\*, application/json, etc.)
|
|
- Knowledge-Store re-indexieren nach Edit (bestehende Pipeline nutzen)
|
|
|
|
**Zu übernehmende UX-Logik (aus Codeeditor extrahieren):**
|
|
- `FileEditProposal`-Datenmodell (`EditStatusEnum`: PENDING → ACCEPTED / REJECTED) in Agent-Datenmodelle kopieren
|
|
- `file_edit_proposal` SSE-Event-Pattern in den Workspace-Agent übernehmen
|
|
- Diff-View-Komponente (`DiffPreviewPanel.tsx`) als eigenständige Shared-Komponente extrahieren
|
|
|
|
**Optionaler Approve/Reject-Mode:**
|
|
- Agent emittiert `file_edit_proposal` SSE-Event mit Old/New-Content
|
|
- Frontend zeigt Diff-View (extrahierte Shared-Komponente)
|
|
- User akzeptiert oder lehnt ab
|
|
- Konfigurierbar: Auto-Apply für kleine Edits, Approve für Dateien > 1 KB
|
|
|
|
**Race-Condition-Risiko:** Gering. Benutzerbezogen, sequenzieller Agent-Zugriff.
|
|
|
|
### 5.3 copyFile -- Vollständige Kopie
|
|
|
|
**Anforderung:** "Datei im Workspace duplizieren."
|
|
|
|
**Bewertung:** Korrekt. Nur File-Level-Kopie sinnvoll. FileData **muss** vollständig dupliziert werden, damit die Kopie unabhängig bearbeitet werden kann (z.B. via `editFile`).
|
|
|
|
**Empfehlung:**
|
|
- Nur einzelne Dateien kopieren, keine ganzen Ordner
|
|
- **Vollständige Duplikation:** FileItem UND FileData werden als eigenständige Einträge mit neuer ID erstellt. Keine Shared-Referenz auf dieselben Daten, da die Kopie editierbar sein muss.
|
|
- Ordner-Kopie als eigenes Feature für später (komplexer wegen Rekursion und Namenskonflikten)
|
|
|
|
### 5.4 createCalendarEvent -- Nicht implementierbar
|
|
|
|
**Anforderung:** "Kalender-Eintrag erstellen."
|
|
|
|
**Bewertung: Noch nicht umsetzbar.** Calendar-API (Microsoft Graph `/calendar/events`) ist nicht gebaut.
|
|
|
|
**Empfehlung:** Aus dem aktuellen Scope entfernen. Als separates Feature planen:
|
|
1. Microsoft Graph Calendar-Endpoints in `connectorMsft.py` implementieren
|
|
2. Workflow-Actions für Calendar erstellen (`outlook.createEvent`, `outlook.listEvents`)
|
|
3. Dann als Agent-Tool exponieren
|
|
|
|
**Bestandsaufnahme Mail-Operationen (für Kontext):**
|
|
|
|
| Operation | Microsoft Outlook | Google Gmail |
|
|
|-----------|-------------------|--------------|
|
|
| Mail-Ordner auflisten | `OutlookAdapter.browse(me/mailFolders)` | `GmailAdapter.browse(labels)` |
|
|
| Mails in Ordner lesen | `OutlookAdapter.browse(me/mailFolders/{id}/messages)` | `GmailAdapter.browse(messages?labelIds=)` |
|
|
| Mail herunterladen | `OutlookAdapter.download(me/messages/{id})` | **Stub** (gibt `b""` zurück) |
|
|
| Mails suchen | `OutlookAdapter.search(me/messages?$search=)` | `GmailAdapter.search(users/me/messages?q=)` |
|
|
| Mail senden | `OutlookAdapter.sendMail(me/sendMail)` | **Nicht implementiert** |
|
|
| Draft erstellen | `composeAndDraftEmailWithContext` (Workflow) | **Nicht implementiert** |
|
|
| Draft senden | `sendDraftEmail` (Workflow) | **Nicht implementiert** |
|
|
| Agent-Tool `sendMail` | Implementiert (nur Outlook trotz Doku "Outlook, Gmail") | **Nicht unterstützt** |
|
|
|
|
**Fazit Mail:** Microsoft Outlook ist vollständig integriert (lesen, suchen, senden, drafts). Google Gmail hat nur Lesen/Suchen (readonly Scopes). Gmail-Senden, Drafts und Download sind nicht implementiert -- bei Bedarf separates Feature.
|
|
|
|
### 5.5 featureInstanceId-Entfernung
|
|
|
|
**Anforderung:** "Die Strukturierung der Daten nach deren Creation Feature Instanz entfernen wir. Dazu eine zusätzliche Spalte ergänzen."
|
|
|
|
**Bewertung:** Guter Ansatz. Die Ordnerstruktur ersetzt die Feature-Instanz-Gruppierung.
|
|
|
|
**Empfehlung:**
|
|
- `featureInstanceId` auf `FileItem` beibehalten (nicht aus dem Modell entfernen)
|
|
- Nicht mehr für Gruppierung nutzen, nur als informatives Metadatum
|
|
- Neue Tabellenspalte "Quelle" zeigt den Feature-Instanz-Namen
|
|
- Kein Datenmigrations-Aufwand nötig -- bestehende Dateien bleiben im Root und können manuell in Ordner verschoben werden
|
|
- Die Zuordnung `featureInstanceId` bei neuen Dateien weiterhin setzen (Audit-Trail)
|
|
|
|
### 5.6 Root "(Global)" -- Multi-Mandanten-Implikation
|
|
|
|
**Anforderung:** "Der Root ist der Folder '(Global)'."
|
|
|
|
**Bewertung:** Konsistent mit dem bestehenden System. Dateien sind bereits benutzerbezogen (`_createdBy` Filter). Der Root-Scope ist pro User, nicht systemweit.
|
|
|
|
**Empfehlung:**
|
|
- Root ist virtuell (kein DB-Eintrag), repräsentiert `folderId=None`
|
|
- Dateien sind weiterhin pro User isoliert (bestehende RBAC-Filter)
|
|
- Label "(Global)" im UI zeigt dem User, dass dies sein persönlicher Root ist
|
|
- Für Multi-Mandanten: Dateien haben `mandateId`, Filter bleibt bestehen
|
|
|
|
### 5.7 searchImages -- Abhängigkeit und Integration
|
|
|
|
**Anforderung:** Aus `doc_enhancement_web_image_actions_pending.md` ein Tool ableiten.
|
|
|
|
**Bewertung:** Das bestehende Konzept ist solide (Google Custom Search API, `WEB_SEARCH_MEDIA` Operation Type). Für den Agent-Tool-Kontext reicht eine vereinfachte Version.
|
|
|
|
**Empfehlung:**
|
|
- Das Agent-Tool `searchImages` als Wrapper um die neue `WEB_SEARCH_MEDIA`-Operation implementieren
|
|
- Ergebnisse als Liste von URLs zurückgeben (der Agent kann dann `downloadFromDataSource` oder einen neuen Mechanismus nutzen, um Bilder herunterzuladen)
|
|
- Google API Key als Voraussetzung klar dokumentieren
|
|
- Fallback: Wenn kein Google API Key konfiguriert, Tool nicht registrieren
|
|
|
|
### 5.8 Dokument-Rendering mit Bildern
|
|
|
|
**Anforderung:** Können professionelle Berichte (DOCX, XLSX, PPTX, PDF, HTML) mit eingebetteten Bildern generiert werden?
|
|
|
|
**Bewertung: Ja, alle 5 Renderer unterstützen Bilder bereits vollständig.**
|
|
|
|
| Renderer | Pfad | Bild-Methode | Bibliothek |
|
|
|----------|------|-------------|------------|
|
|
| DOCX | `renderers/rendererDocx.py` | `_renderJsonImage()` → `doc.add_picture()` | python-docx |
|
|
| XLSX | `renderers/rendererXlsx.py` | `_addImageToExcel()` → `sheet.add_image()` | openpyxl |
|
|
| PPTX | `renderers/rendererPptx.py` | `_addImagesToSlide()` → `slide.shapes.add_picture()` | python-pptx |
|
|
| PDF | `renderers/rendererPdf.py` | `_renderJsonImage()` → `ReportLabImage` | reportlab |
|
|
| HTML | `renderers/rendererHtml.py` | `_renderJsonImage()` → `<img src="data:image/...;base64,...">` | native |
|
|
|
|
**Gemeinsames Bild-Format (alle Renderer):**
|
|
```json
|
|
{
|
|
"type": "image",
|
|
"content": {
|
|
"base64Data": "<base64-encoded image>",
|
|
"altText": "Bildbeschreibung",
|
|
"caption": "Optionale Bildunterschrift"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Basis-Klasse** (`documentRendererBaseTemplate.py`): Bietet `_validateImageData()`, `_getImageDimensions()`, `_resizeImageIfNeeded()` als Shared-Funktionen.
|
|
|
|
**Fazit:** Kein Handlungsbedarf für Bild-Rendering. Der Agent kann Bilder (z.B. via `generateImage` oder `searchImages` + Download) als Base64-Daten in das Dokument-Schema einbetten, und alle Renderer verarbeiten diese korrekt.
|
|
|
|
### 5.9 neutralizeData -- Scope
|
|
|
|
**Anforderung:** "Text/Datei anonymisieren."
|
|
|
|
**Bewertung:** `serviceNeutralization` existiert, ist aber Feature-spezifisch (Neutralization Feature). Als Agent-Tool muss es Feature-unabhängig aufrufbar sein.
|
|
|
|
**Empfehlung:**
|
|
- Read-Only: Gibt anonymisierten Text zurück, ändert das Original nicht
|
|
- Für Dateien: Temporär extrahieren, neutralisieren, Ergebnis als neuen Text zurückgeben
|
|
- Feature-Abhängigkeit prüfen: Wenn Neutralization-Feature nicht lizenziert, Tool nicht registrieren
|
|
|
|
---
|
|
|
|
## 6. Zusammenfassung und Priorisierung
|
|
|
|
### Tool-Übersicht nach Aufwand und Nutzen
|
|
|
|
| Tool | Aufwand | Nutzen | Priorität | Phase |
|
|
|------|---------|--------|-----------|-------|
|
|
| `deleteFile` | Niedrig | Hoch | **Must** | 1 |
|
|
| `renameFile` | Niedrig | Hoch | **Must** | 1 |
|
|
| `readUrl` | Niedrig | Hoch | **Must** | 1 |
|
|
| `translateText` | Niedrig | Mittel | **Should** | 1 |
|
|
| `deleteFolder` | Mittel | Hoch | **Must** | 2 |
|
|
| `renameFolder` | Niedrig | Mittel | **Should** | 2 |
|
|
| `moveFolder` | Mittel | Mittel | **Should** | 2 |
|
|
| `copyFile` | Niedrig | Mittel | **Should** | 2 |
|
|
| `editFile` | Niedrig (Codeeditor-Logik vorhanden) | Hoch | **Must** | 2 |
|
|
| `speechToText` | Niedrig | Mittel | **Should** | 3 |
|
|
| `detectLanguage` | Niedrig | Niedrig | **Could** | 3 |
|
|
| `searchImages` | Hoch | Mittel | **Should** | 3 |
|
|
| `neutralizeData` | Mittel | Niedrig | **Could** | 3 |
|
|
| `executeCode` | Hoch | Hoch | **Should** | 3 |
|
|
| `createCalendarEvent` | Hoch | Mittel | **Won't** (vorerst) | - |
|
|
|
|
### Geschätzter Gesamtaufwand
|
|
|
|
| Bereich | Aufwand |
|
|
|---------|---------|
|
|
| Phase 1: Quick-Win Tools | 2-3 Tage |
|
|
| Phase 2: Dateisystem-Backend + Tools | 4-5 Tage |
|
|
| Phase 3: Erweiterte Tools | 5-7 Tage |
|
|
| UI: Dateien-Seite Split-View | 3-4 Tage |
|
|
| UI: Folder-Tree Komponente | 2-3 Tage |
|
|
| UI: Workspace-Integration | 1-2 Tage |
|
|
| **Gesamt** | **17-24 Tage** |
|
|
|
|
---
|
|
|
|
## 7. Referenzen
|
|
|
|
| Dokument | Pfad |
|
|
|----------|------|
|
|
| AI Agent Architecture | `wiki/concepts/AI-Agent-Architecture-Konzept.md` |
|
|
| Web Image Search Konzept | `local/pending/doc_enhancement_web_image_actions_pending.md` |
|
|
| Codeeditor (Logik extrahieren, Feature wird entfernt) | `gateway/modules/features/codeeditor/routeFeatureCodeeditor.py` |
|
|
| Codeeditor Datenmodell (extrahieren) | `gateway/modules/features/codeeditor/datamodelCodeeditor.py` |
|
|
| Codeeditor Response Parser (extrahieren) | `gateway/modules/features/codeeditor/responseParser.py` |
|
|
| Codeeditor DiffPreview (als Shared-Komponente extrahieren) | `frontend_nyla/src/pages/views/codeeditor/DiffPreviewPanel.tsx` |
|
|
| Dokument-Renderer (Bild-Support) | `gateway/modules/serviceCenter/services/serviceGeneration/renderers/` |
|
|
| FileItem Datenmodell | `gateway/modules/datamodels/datamodelFiles.py` |
|
|
| FileFolder Datenmodell | `gateway/modules/datamodels/datamodelFileFolder.py` |
|
|
| DB-Operationen | `gateway/modules/interfaces/interfaceDbManagement.py` |
|
|
| Agent Tools | `gateway/modules/serviceCenter/services/serviceAgent/mainServiceAgent.py` |
|
|
| Tool Registry | `gateway/modules/serviceCenter/services/serviceAgent/toolRegistry.py` |
|
|
| Frontend FileBrowser | `frontend_nyla/src/pages/views/workspace/FileBrowser.tsx` |
|
|
| Frontend FilesPage | `frontend_nyla/src/pages/basedata/FilesPage.tsx` |
|
|
| DataSourcePanel (Tree-Referenz) | `frontend_nyla/src/pages/views/workspace/DataSourcePanel.tsx` |
|