--- name: Cursor-Style Chat Feature MVP overview: Integration eines Cursor-artigen File-Editing-Chat-Features als neues Feature "codeeditor" im Gateway und der Nyla UI. Nutzt aicore-Modelle direkt, Chat-Datenmodelle vom Chatplayground, SSE-Streaming vom Chatbot-Feature. Nur Text-Dokumente (Markdown, JSON, YAML, Code). Dateien werden hochgeladen (kein SharePoint), spaeter mit virtuellen Folder-Tags strukturiert. Apply erzeugt neue lokale Dokument-Versionen. todos: - id: extend-workflow-mode content: WorkflowModeEnum um WORKFLOW_CODEEDITOR erweitern in datamodelChat.py + FileContext/FileEditProposal Models status: pending - id: backend-feature-scaffold content: "Feature-Scaffold: mainCodeeditor.py (Registrierung) + routeFeatureCodeeditor.py (Endpoints, Vorlage: chatplayground)" status: pending - id: file-context-manager content: "fileContextManager.py: Hochgeladene Text-Dateien laden, Workspace-Snapshot erstellen (kein SharePoint)" status: pending - id: prompt-assembly content: "promptAssembly.py: Cursor-artiger System Prompt Builder mit Datei-Kontext und Format-Instruktionen" status: pending - id: response-parser content: "responseParser.py: AI-Antwort in Document-Segmente parsen (text, code_block, file_edit, etc.)" status: pending - id: frontend-feature-register content: "FeatureView.tsx: codeeditor Views registrieren, CodeEditorPage + FileBrowserPanel + DiffPreviewPanel erstellen" status: pending - id: frontend-hooks content: "useCodeEditor.ts Hook: Erweitert Playground-Pattern um File-Selection und Edit-Management" status: pending isProject: false --- # MVP: Cursor-Style File-Editing Chat Feature ("CodeEditor") ## Professionelle Einschaetzung ### Kernfrage: aicore-Modelle direkt oder ueber Chat-Komponente? **Empfehlung: Die bestehenden aicore-Modelle direkt nutzen** (nicht ueber eine externe Cursor-Chat-Komponente). Begruendung: - Die aicore-Infrastruktur (`aicoreModelRegistry`, `aicoreModelSelector`, Plugin-System) ist bereits produktionsreif mit Failover, Billing, RBAC und Multi-Provider-Support - Eine externe Cursor-Komponente wuerde eine Abhaengigkeit schaffen, die schwer zu kontrollieren ist - Der Mehrwert liegt nicht im LLM-Aufruf (den beherrscht aicore), sondern in der **Prompt-Orchestrierung** (System Prompt + Context + Tool Definitions) und dem **Response Parsing** (Antwort in Dokument-Segmente zerlegen) - Der neue "Cursor-Style" Layer wird **auf aicore aufgebaut**, nicht neben oder statt aicore ### Was vom Chatplayground uebernommen werden kann Sehr viel -- die Grundarchitektur ist ideal: - **ChatWorkflow** Datenmodell: 1:1 wiederverwendbar (neuer `workflowMode: "CodeEditor"`) - **ChatMessage** + **ChatDocument**: Vollstaendig wiederverwendbar fuer Chat-Verlauf und Datei-Referenzen - **Polling-Mechanismus** (`getUnifiedChatData` mit `afterTimestamp`): Sofort nutzbar - **SSE-Infrastruktur** (aus Chatbot-Feature): Kann fuer Echtzeit-Streaming aktiviert werden - **PlaygroundPage UI-Pattern**: Resizable Two-Column Layout, Messages-Komponente, File-Upload, Input-Footer - **Route-Pattern** (`routeFeatureChatplayground.py`): Als Vorlage fuer neue Feature-Route - **Feature-Registrierung**: `VIEW_COMPONENTS` Registry in `FeatureView.tsx`, Backend `mainChatplayground.py` ### Was NEU gebaut werden muss 1. **File-Context-Manager** (Backend): Hochgeladene Text-Dateien als "Workspace" laden und als Kontext bereitstellen (kein SharePoint, spaeter virtuelle Folder-Tags) 2. **Prompt Assembly Service** (Backend): System Prompt mit File-Kontext und Cursor-artigen Instruktionen zusammenbauen 3. **Response Document Parser** (Backend): AI-Antwort in typisierte Dokument-Segmente zerlegen (text, code_block, file_edit, etc.) 4. **Diff-Preview UI** (Frontend): Text-Aenderungen als Diff anzeigen mit Accept/Reject 5. **File-List Panel** (Frontend): Hochgeladene Dateien auflisten und als Kontext auswaehlen (spaeter: virtuelle Folder-Tags) 6. **SSE-Integration** (Backend+Frontend): Echtzeit-Streaming ueber bestehende EventManager-Infrastruktur --- ## Architektur ```mermaid flowchart TB subgraph ui [Nyla UI - Frontend] CodeEditorPage["CodeEditorPage\n(neue View)"] FileList["FileListPanel\n(hochgeladene Dateien)"] ChatPanel["ChatPanel\n(Messages + SSE)"] DiffPreview["DiffPreviewPanel\n(Text-Diffs)"] CodeEditorPage --> FileList CodeEditorPage --> ChatPanel CodeEditorPage --> DiffPreview end subgraph gw [Gateway - Backend] Route["routeFeatureCodeeditor.py\n(FastAPI Endpoints)"] SSE["SSE Stream Endpoint\n(EventManager)"] FileCtx["fileContextManager.py\n(Text-Dateien laden)"] PromptAsm["promptAssembly.py\n(System Prompt Builder)"] RespParse["responseParser.py\n(Document Segmentation)"] Route --> FileCtx Route --> PromptAsm PromptAsm --> AiService["serviceAi\n(bestehend)"] AiService --> AiCore["aicore\n(ModelRegistry + Plugins)"] RespParse --> Route RespParse --> SSE end subgraph data [Datenspeicher] DB["Gateway DB\n(interfaceDbComponent)\nHochgeladene Dateien"] end ChatPanel -->|"POST /api/codeeditor/.../start"| Route ChatPanel -->|"GET .../stream (SSE)"| SSE FileList -->|"GET .../files"| Route DiffPreview -->|"POST .../apply"| Route FileCtx --> DB ``` --- ## MVP Scope: Konkrete Implementierung ### Backend: Gateway **1. Neues Feature `codeeditor`** - Datei: `gateway/modules/features/codeeditor/mainCodeeditor.py` - Registrierung analog zu `mainChatplayground.py` (RBAC, Feature-Config) **2. Routes** - Datei: `gateway/modules/features/codeeditor/routeFeatureCodeeditor.py` - Kopie von `routeFeatureChatplayground.py` als Basis, erweitert um: | Endpoint | Methode | Beschreibung | | -------------------------------------- | ------- | ---------------------------------------------------------- | | `/{instanceId}/start` | POST | Workflow starten (nutzt `chatStart` mit mode `CodeEditor`) | | `/{instanceId}/{workflowId}/stop` | POST | Workflow stoppen | | `/{instanceId}/{workflowId}/stream` | GET | SSE-Stream fuer Echtzeit-Updates (Messages, Logs, Edits) | | `/{instanceId}/{workflowId}/chatData` | GET | Fallback-Polling fuer Chat-Daten | | `/{instanceId}/workflows` | GET | Workflows auflisten | | `/{instanceId}/files` | GET | Hochgeladene Text-Dateien auflisten | | `/{instanceId}/files/{fileId}/content` | GET | Text-Datei-Inhalt laden | | `/{instanceId}/{workflowId}/apply` | POST | Aenderung als neue Dokument-Version speichern | **3. WorkflowMode Erweiterung** - Datei: `gateway/modules/datamodels/datamodelChat.py` - Neuer Enum-Wert: `WORKFLOW_CODEEDITOR = "CodeEditor"` in `WorkflowModeEnum` **4. File Context Manager** - Datei: `gateway/modules/features/codeeditor/fileContextManager.py` - Laedt hochgeladene Text-Dateien aus Gateway DB (`interfaceDbComponent`) - Unterstuetzte Formate: `.md`, `.txt`, `.json`, `.yaml`, `.yml`, `.xml`, `.csv`, `.py`, `.js`, `.ts`, `.html`, `.css`, `.sql` - Baut einen "Workspace-Snapshot": Dateiliste + Inhalte der vom User ausgewaehlten Dateien - Validiert MIME-Types (nur text-basierte Dateien akzeptieren) - Spaeter erweiterbar: virtuelle Folder-Tags pro Datei fuer Strukturierung **5. Prompt Assembly** - Datei: `gateway/modules/features/codeeditor/promptAssembly.py` - Baut System Prompt nach Cursor-Muster (dokumentiert in `wiki/cursor-doc/doc_cursor_ai_agent_architecture.md`) - Injiziert: Datei-Kontexte, Benutzer-Instruktionen, Antwort-Format-Vorgaben - Nutzt `aiService.callAiContent()` oder `interfaceAiObjects.callWithTextContext()` als LLM-Aufruf **6. Response Document Parser** - Datei: `gateway/modules/features/codeeditor/responseParser.py` - Parst AI-Antwort in typisierte Segmente: `text`, `code_block`, `code_reference`, `file_edit` - Speichert Segmente als erweiterte `ChatMessage` Eintraege (mit `actionMethod: "codeeditor"`) - Spezifikation: `wiki/cursor-doc/doc_cursor_response_json_structure.md` ### Frontend: Nyla UI **7. Feature-Registrierung** - Datei: `frontend_nyla/src/pages/FeatureView.tsx` - Neuer Eintrag in `VIEW_COMPONENTS`: ```typescript codeeditor: { editor: CodeEditorPage, workflows: WorkflowsPage, // wiederverwendet } ``` **8. CodeEditorPage** - Datei: `frontend_nyla/src/pages/views/codeeditor/CodeEditorPage.tsx` - Drei-Panel-Layout (File-Browser links, Chat mitte, Diff-Preview rechts) - Nutzt bestehende `Messages` Komponente, `useResizablePanels`, `usePlayground`-Pattern **9. File List Panel** - Datei: `frontend_nyla/src/components/CodeEditor/FileListPanel.tsx` - Flache Liste der hochgeladenen Text-Dateien mit Checkbox-Auswahl - Upload-Button fuer neue Dateien (Drag & Drop wiederverwendet aus Playground) - Ausgewaehlte Dateien werden als Kontext an den Chat gesendet (analog `listFileId`) - Spaeter erweiterbar: virtuelle Folder-Tags als Gruppierung **10. Diff Preview Panel** - Datei: `frontend_nyla/src/components/CodeEditor/DiffPreviewPanel.tsx` - Zeigt `file_edit` Segmente aus der AI-Antwort als Text-Diff an - Accept/Reject Buttons pro Aenderung - Accept erzeugt neue Dokument-Version (POST `/{instanceId}/{workflowId}/apply`) - MVP: einfacher Side-by-Side Text-Diff (kein vollstaendiger Code-Editor noetig) **11. Hooks** - Datei: `frontend_nyla/src/hooks/useCodeEditor.ts` - Erweitert `useDashboardInputForm` Pattern um: - `selectedFiles: string[]` (ausgewaehlte Kontext-Dateien) - `pendingEdits: FileEdit[]` (vorgeschlagene Aenderungen) - `applyEdit(editId)` / `rejectEdit(editId)` Aktionen ### Datenmodell-Erweiterungen **12. Neue Pydantic Models** (in bestehendem `datamodelChat.py` oder eigenem File) ```python class FileContext(BaseModel): fileId: str fileName: str content: Optional[str] = None mimeType: str tags: List[str] = Field(default_factory=list) # virtuelle Folder-Tags (spaeter) class FileEditProposal(BaseModel): id: str = Field(default_factory=lambda: str(uuid.uuid4())) fileId: str # Referenz auf bestehende Datei fileName: str operation: str # "edit" | "create" oldContent: Optional[str] = None newContent: str diffSummary: Optional[str] = None # Kurzbeschreibung der Aenderung status: str = "pending" # "pending" | "accepted" | "rejected" class FileVersion(BaseModel): id: str = Field(default_factory=lambda: str(uuid.uuid4())) sourceFileId: str # Original-Datei editProposalId: str # Referenz auf akzeptiertes FileEditProposal newFileId: str # Neue Datei-Version in DB createdAt: float = Field(default_factory=getUtcTimestamp) ``` --- ## Entschiedene Design-Entscheide 1. **Datenquelle**: Hochgeladene Dateien im System (kein SharePoint). Spaeter: virtuelle Folder-Tags pro Datei fuer Strukturierung 2. **Dateitypen**: Nur Text-basierte Dokumente (Markdown, JSON, YAML, Code, etc.) 3. **Apply-Mechanismus**: Erzeugt neue lokale Dokument-Version in der DB (keine externe Synchronisation) 4. **Streaming**: SSE ueber bestehende `EventManager`-Infrastruktur aus dem Chatbot-Feature --- ## SSE-Integration (Details) Nutzt die bestehende Infrastruktur aus `gateway/modules/features/chatbot/streaming/events.py`: - **EventManager** Singleton: `get_event_manager()` - verwaltet async Queues pro Workflow - **Event-Emission**: In `interfaceDbChat.createMessage()` und `createLog()` bereits eingebaut - **Neuer SSE-Endpoint**: `GET /api/codeeditor/{instanceId}/{workflowId}/stream` - **Event-Typen fuer CodeEditor**: - `chatdata` (bestehend): Messages, Logs, Stats - `file_edit` (neu): FileEditProposal Events fuer Echtzeit-Diff-Updates - `file_version` (neu): Neue Datei-Version erstellt (nach Apply) - **Frontend**: `useCodeEditor` Hook oeffnet `EventSource` statt Polling - **Fallback**: `chatData` Polling-Endpoint bleibt als Fallback verfuegbar