{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"tasks\": [\n {\n \"id\": 463,\n \"uuid\": \"c933f175-c7d6-4ed8-aad5-7216d3479c67\",\n \"title\": \"HTMX: chat\/index.php - Chat-Interface\",\n \"description\": \"# HTMX: chat\/index.php - Vollständige Analyse\\n\\n## Status\\n**Typ:** human_task (manuelle Bearbeitung erforderlich)\\n**Komplexität:** HOCH - Echtes Chat-Interface mit SSE-Streaming\\n\\n---\\n\\n## ✅ Phase 1: SECURITY FIXES - ERLEDIGT (27.12.2025)\\n\\n| # | Datei | Zeile | Status |\\n|---|-------|-------|--------|\\n| 1 | index.php | 30 | ✅ CSRF hinzugefügt |\\n| 2 | index.php | 55 | ✅ CSRF hinzugefügt |\\n| 3 | session-list.php | 23 | ✅ CSRF hinzugefügt |\\n| 4 | system-prompt-modal.php | 19 | ✅ CSRF hinzugefügt |\\n\\n---\\n\\n## ✅ Phase 2: fetch() CSRF - ERLEDIGT (27.12.2025)\\n\\n| # | Datei | Zeile | Status |\\n|---|-------|-------|--------|\\n| 5 | index.php | ~534 | ✅ SSE formData.append CSRF |\\n| 6 | index.php | ~731 | ✅ Config formData.append CSRF |\\n| 7 | index.php | ~774 | ✅ Title body += CSRF |\\n\\n---\\n\\n## ✅ Phase 3: Abgeschlossen\\n\\nSSE-Streaming und Config-Panel bleiben bei fetch() (technisch sinnvoll).\\nCSRF-Tokens wurden zu allen POST-Requests hinzugefügt.\\n\\n---\\n\\n## Betroffene Dateien - ALLE FERTIG\\n\\n| Datei | Status |\\n|-------|--------|\\n| `\/src\/View\/chat\/index.php` | ✅ Fertig |\\n| `\/src\/View\/chat\/partials\/session-list.php` | ✅ Fertig |\\n| `\/src\/View\/chat\/partials\/system-prompt-modal.php` | ✅ Fertig |\\n\\n---\\n\\n## Checkliste - KOMPLETT\\n\\n- [x] Phase 1.1: CSRF auf index.php:30 (Delete All)\\n- [x] Phase 1.2: CSRF auf index.php:55 (Delete Session)\\n- [x] Phase 1.3: CSRF auf session-list.php:23 (Delete Session)\\n- [x] Phase 1.4: CSRF auf system-prompt-modal.php:19 (POST Form)\\n- [x] Phase 2.1: CSRF in SSE fetch() (index.php ~Zeile 534)\\n- [x] Phase 2.2: CSRF in Config-POST fetch() (index.php ~Zeile 731)\\n- [x] Phase 2.3: CSRF in Title-Update fetch() (index.php ~Zeile 774)\\n- [ ] Testen: Alle Delete-Operationen\\n- [ ] Testen: Chat-Streaming\\n- [ ] Testen: Config-Speichern\\n- [ ] Testen: Title-Edit\",\n \"type\": \"human_task\",\n \"status\": \"completed\",\n \"created_by\": \"mcp-tasks\",\n \"created_by_type\": \"ai\",\n \"parent_task_id\": null,\n \"due_date\": null,\n \"created_at\": \"2025-12-27T12:05:55.383802\",\n \"updated_at\": \"2025-12-27T12:47:14.321217\",\n \"completed_at\": \"2025-12-27T12:47:14.321221\",\n \"metadata\": {}\n },\n {\n \"id\": 442,\n \"uuid\": \"b22debfc-fde0-4a34-bf6d-08a0bd96110e\",\n \"title\": \"PDF-Rotationserkennung und -korrektur implementieren\",\n \"description\": \"## KONTEXT\\n\\nPDF-Dokumente enthalten teilweise um 90°\/180°\/270° gedrehte Seiten. Die aktuelle Pipeline ignoriert die Rotation, was zu:\\n- Fehlerhafter OCR-Extraktion\\n- Unlesbaren Vision-Analysen\\n- Korrupten Embeddings\\n\\nführt.\\n\\n---\\n\\n## CODE-ANALYSE\\n\\n### Betroffene Dateien\\n\\n| Datei | Funktion | Zeilen | Problem |\\n|-------|----------|--------|---------|\\n| `extract.py` | `extract_pdf()` | 13-45 | Keine Rotationserkennung |\\n| `vision.py` | `pdf_to_images()` | 30-67 | Rotation wird ignoriert |\\n| `config.py` | OCR-Settings | 74-76 | OCR_ENABLED=True |\\n\\n### Aktuelle Implementierung\\n\\n**extract.py:13-45**\\n```python\\ndef extract_pdf(file_path):\\n import fitz # PyMuPDF\\n doc = fitz.open(file_path)\\n pages = []\\n \\n for page_num, page in enumerate(doc):\\n text = page.get_text() # ← Ignoriert Rotation\\n \\n # OCR-Fallback (Zeile 24-40)\\n if OCR_ENABLED and len(text.strip()) < 50:\\n pix = page.get_pixmap(dpi=300) # ← Rotation nicht berücksichtigt\\n img = Image.open(io.BytesIO(img_data))\\n ocr_text = pytesseract.image_to_string(img, lang=OCR_LANGUAGE)\\n # ← Keine Orientierungserkennung\\n```\\n\\n**vision.py:30-67**\\n```python\\ndef pdf_to_images(file_path, dpi=IMAGE_DPI):\\n import fitz\\n doc = fitz.open(file_path)\\n \\n for page_num in range(len(doc)):\\n page = doc[page_num]\\n mat = fitz.Matrix(dpi \/ 72, dpi \/ 72)\\n pix = page.get_pixmap(matrix=mat) # ← Rotation ignoriert\\n```\\n\\n### Systemzustand\\n\\n| Komponente | Status |\\n|------------|--------|\\n| PyMuPDF | ✓ 1.26.7 installiert |\\n| pytesseract | ✓ 0.3.13 installiert |\\n| Pillow | ✓ 12.0.0 installiert |\\n| **tesseract binary** | ❌ **NICHT INSTALLIERT** |\\n| OCR_ENABLED | True (aber funktioniert nicht!) |\\n\\n---\\n\\n## LÖSUNG: Mehrstufige Orientierungserkennung\\n\\n### Architektur\\n\\n```\\n┌─────────────────────────────────────────────────────────┐\\n│ Stufe 1: PDF-Metadaten (page.rotation) │\\n│ PyMuPDF liest \/Rotate Flag aus PDF │\\n│ → Schnell, kostenlos, 0ms │\\n└─────────────────────┬───────────────────────────────────┘\\n │ Falls rotation == 0\\n ▼\\n┌─────────────────────────────────────────────────────────┐\\n│ Stufe 2: Tesseract OSD (Orientation Script Detection) │\\n│ pytesseract.image_to_osd(img) │\\n│ → Erkennt 0°\/90°\/180°\/270°, Confidence-Score │\\n│ → ~50-100ms pro Seite │\\n└─────────────────────┬───────────────────────────────────┘\\n │ Falls Confidence < 2.0\\n ▼\\n┌─────────────────────────────────────────────────────────┐\\n│ Stufe 3: Vision-LLM Fallback (optional) │\\n│ \\\"Ist diese Seite korrekt orientiert?\\\" │\\n│ → Für Bilder ohne Text │\\n└─────────────────────────────────────────────────────────┘\\n```\\n\\n### Implementierung\\n\\n#### 1. Voraussetzung: Tesseract installieren\\n\\n```bash\\napt-get install tesseract-ocr tesseract-ocr-deu\\n```\\n\\n#### 2. Neue Datei: `\/var\/www\/scripts\/pipeline\/orientation.py`\\n\\n```python\\n\\\"\\\"\\\"\\nPage Orientation Detection Module\\nDetects and corrects rotated PDF pages.\\n\\\"\\\"\\\"\\n\\nimport io\\nfrom PIL import Image\\nimport pytesseract\\nimport fitz # PyMuPDF\\n\\nfrom db import db\\n\\n\\ndef detect_orientation(image_bytes: bytes) -> dict:\\n \\\"\\\"\\\"\\n Detect page orientation using Tesseract OSD.\\n \\n Args:\\n image_bytes: PNG\/JPEG image as bytes\\n \\n Returns:\\n dict: {\\n 'rotation': int (0, 90, 180, 270),\\n 'confidence': float,\\n 'script': str,\\n 'method': str ('osd' or 'fallback')\\n }\\n \\\"\\\"\\\"\\n try:\\n img = Image.open(io.BytesIO(image_bytes))\\n osd = pytesseract.image_to_osd(img, output_type=pytesseract.Output.DICT)\\n \\n return {\\n 'rotation': osd.get('rotate', 0),\\n 'confidence': osd.get('orientation_conf', 0.0),\\n 'script': osd.get('script', 'Unknown'),\\n 'method': 'osd'\\n }\\n except Exception as e:\\n db.log(\\\"WARNING\\\", f\\\"OSD detection failed: {e}\\\")\\n return {\\n 'rotation': 0,\\n 'confidence': 0.0,\\n 'script': 'Unknown',\\n 'method': 'fallback'\\n }\\n\\n\\ndef get_page_rotation(page) -> int:\\n \\\"\\\"\\\"\\n Get effective rotation for a PDF page.\\n \\n Combines PDF metadata rotation with detected orientation.\\n \\n Args:\\n page: PyMuPDF page object\\n \\n Returns:\\n int: Total rotation needed (0, 90, 180, 270)\\n \\\"\\\"\\\"\\n # Stufe 1: PDF-Metadaten\\n pdf_rotation = page.rotation # 0, 90, 180, 270\\n \\n if pdf_rotation != 0:\\n return pdf_rotation\\n \\n # Stufe 2: Tesseract OSD\\n pix = page.get_pixmap(dpi=150) # Lower DPI for speed\\n img_bytes = pix.tobytes(\\\"png\\\")\\n \\n detection = detect_orientation(img_bytes)\\n \\n if detection['confidence'] >= 2.0:\\n return detection['rotation']\\n \\n return 0\\n\\n\\ndef rotate_image(image_bytes: bytes, rotation: int) -> bytes:\\n \\\"\\\"\\\"\\n Rotate image by specified degrees.\\n \\n Args:\\n image_bytes: Original image\\n rotation: Degrees to rotate (90, 180, 270)\\n \\n Returns:\\n bytes: Rotated image as PNG\\n \\\"\\\"\\\"\\n if rotation == 0:\\n return image_bytes\\n \\n img = Image.open(io.BytesIO(image_bytes))\\n \\n # PIL rotation is counter-clockwise, PDF is clockwise\\n rotated = img.rotate(-rotation, expand=True)\\n \\n output = io.BytesIO()\\n rotated.save(output, format='PNG')\\n return output.getvalue()\\n```\\n\\n#### 3. Integration in extract.py\\n\\n**Änderung in `extract_pdf()` (Zeile 20-27 einfügen):**\\n\\n```python\\ndef extract_pdf(file_path):\\n import fitz\\n from orientation import get_page_rotation, rotate_image\\n \\n doc = fitz.open(file_path)\\n pages = []\\n \\n for page_num, page in enumerate(doc):\\n # NEU: Rotation erkennen\\n rotation = get_page_rotation(page)\\n \\n # Text mit korrekter Rotation extrahieren\\n if rotation != 0:\\n # Seite vor Extraktion rotieren\\n page.set_rotation(rotation)\\n \\n text = page.get_text()\\n \\n # OCR-Fallback mit rotiertem Bild\\n if OCR_ENABLED and len(text.strip()) < 50:\\n pix = page.get_pixmap(dpi=300)\\n img_data = pix.tobytes(\\\"png\\\")\\n \\n # NEU: Bild rotieren falls nötig\\n if rotation != 0:\\n img_data = rotate_image(img_data, rotation)\\n \\n img = Image.open(io.BytesIO(img_data))\\n ocr_text = pytesseract.image_to_string(img, lang=OCR_LANGUAGE)\\n```\\n\\n#### 4. Integration in vision.py\\n\\n**Änderung in `pdf_to_images()` (Zeile 46-54):**\\n\\n```python\\ndef pdf_to_images(file_path, dpi=IMAGE_DPI):\\n import fitz\\n from orientation import get_page_rotation, rotate_image\\n \\n doc = fitz.open(file_path)\\n pages = []\\n \\n for page_num in range(len(doc)):\\n page = doc[page_num]\\n \\n # NEU: Rotation erkennen\\n rotation = get_page_rotation(page)\\n \\n mat = fitz.Matrix(dpi \/ 72, dpi \/ 72)\\n pix = page.get_pi... [TRUNCATED-5f95f1ab454fa2bd]"
}
]
}