wiki/z-archive/c-work/2026-03-cursor-style-chat.md
2026-04-06 00:46:32 +02:00

263 lines
12 KiB
Markdown

---
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