import type { APIRoute } from 'astro'; export const prerender = false; /** * Maschinen-/KI-lesbare Kurzdoku unter /llms.txt (öffentlich, ohne Geheimnisse). * Beschreibt Zweck, Fähigkeiten und die HTTP-/MCP-Schnittstelle von Klarbild, * damit ein KI-Agent das Tool ohne Weboberfläche bedienen kann. */ const BODY = `# Klarbild > Selbst gehostetes KI-Bildwerkzeug: verwandelt Screenshots und Fundstücke in > saubere, druckfertige Bilder (bereinigen, freistellen, exakte Fotoformate, > The-Frame-Querformat, Sticker mit Kontur), liefert an Picdrop (SFTP/FTPS) > aus und sichert auf beliebige Backup-Ziele (z. B. NAS). Zusätzlich ein > KI-freies Druckmodul: Bilder exakt auf physische Maße bringen und mehrere > davon in 100-%-Größe mit Schnittmarken auf einen Druckbogen setzen (PDF). > Bedienung über Web, Telegram-Bot und HTTP-API/MCP. Basis-URL: https://klarbild.heidrich-digital.de Sprache der Oberfläche: Deutsch. Stack: Astro 5 (SSR) · Postgres · sharp · pg-boss. ## Authentifizierung (für Agenten) - Header: \`Authorization: Bearer \` (Admin → „Automatisierung / MCP-Zugriff"). - Der Token gilt für \`/api/*\` — NICHT für \`/api/admin/*\` (nur per Login-Session). - Ohne Token/Session antworten API-Routen mit 401. ## Kernbegriffe - Modus (mode): \`each\` (Screenshot bereinigen/freistellen/formatieren), \`compose\` (ein Bild umwandeln ODER mehrere kombinieren, mit Textbeschreibung), \`generate\` (neues Bild allein aus Text). - Aufgaben (tasks, nur bei each): \`clean\`, \`cutout\`, \`format\`, \`contour\`. - Rezept (recipe): gespeicherte Voreinstellung. Auftrag (job): ein Stapel; Position (item): ein Bild. - Auftrags-Status: queued, running, paused, done, failed, cancelled. \`failed\` = alle Positionen fehlgeschlagen. ## Formate (output_format) - Feste Schlüssel: 9x13,10x15,13x18,15x20,20x30,30x40,30x45,40x50,40x60,50x70,60x90, A4,A3,A2,20x20,30x30, theframe (3840x2160), hochformat (2160x3840), keep (Original behalten). - Freie Formate ohne Vorgabe: \`BREITExHOEHE\` in cm (z. B. \`25x35\`) oder \`sticker\` für N×N cm (z. B. \`sticker5\` = 5×5 cm). Grenze 300 cm. Exakte Pixel: round(cm/2.54*dpi). - Dateiformat (output_ext): \`png\` (verlustfrei, Transparenz) oder \`jpg\` (klein, Picdrop-freundlich). JPG nur ohne Transparenz; freigestellte Motive bleiben immer PNG. Global (Admin) oder pro Rezept. ## HTTP-API (Auswahl, JSON) - GET /api/health — Status (öffentlich). - GET /api/me — aktueller Nutzer/Rechte. - GET /api/models — verfügbare Bildmodelle (Qualitätsstufen). - GET /api/recipes — Rezepte/Presets auflisten. - POST /api/recipes — Rezept anlegen. Body u. a.: name, mode, tasks[], output_format, orientation(portrait|landscape), crop_mode(crop|extend), dpi, contour_mm, output_ext(png|jpg|null), delivery(library|picdrop|both), picdrop_gallery, delivery_target_id. - DELETE /api/recipes/:id — Rezept löschen. - GET /api/delivery-targets — Auslieferungs-/Backup-Ziele. - POST /api/jobs — Auftrag starten. Body: { recipe, mode, delivery, private, prompt_text?(compose/generate), sources:[{source_path, filename}] }. Antwort: { jobId }. - GET /api/jobs — letzte Aufträge. GET /api/jobs/:id — Auftrag + Positionen (inkl. error_message, finished_at). - POST /api/jobs/:id/{pause|resume|cancel|retry-failed|delete}. - POST /api/items/:id/{retry|reuse|alternative}. - GET /api/items/:id/file — Ergebnisbild. Query: ?thumb=1 (Vorschau), ?preview=1 (kleines JPG fürs Vollbild), ?download=1 (als Datei), ?src=1 (Quelle). Content-Type wird aus den Magic Bytes bestimmt (PNG/JPG/WEBP). ## Druckmodul (ohne KI, /druck) Rein lokale Geometrie: Zuschnitt (sharp) + PDF (pdf-lib). Kein Modell, keine Kosten. - Maßangaben: \`12x15\` = 12×15 cm · \`35x45mm\` · \`5\` = 5×5 cm · \`4:3/15\` = Verhältnis 4:3, längere Kante 15 cm. - Papierformate (id): A6,A5,A4,A3,A3plus(329×483 mm),A2, F9x13,F10x15,F13x18,F15x20,F20x30, Letter, Legal — oder freies Maß. - Bildformate (id): P35x45 (biometrisch), P50x50, K20x30,K30x40,K40x50,K45x60,K60x90, S9x13,S10x15,S12x15,S13x18,S15x20,S18x24,S20x30,S30x40,S30x45,S40x50,S40x60,S50x70, Q10x10,Q13x13,Q20x20,Q30x30, DA6,DA5,DA4,DA3. - Schnitthilfen (marks.mode): \`none\` · \`corner\` (Eckmarken außerhalb des Endformats, Standard 4 mm lang, 3 mm Versatz, 0,25 pt Haarlinie) · \`grid\` (durchgehende Linien über den Bogen, laufen nie durch ein Motiv). - Beschnittzugabe (bleedMm): das Bild ragt je Seite darüber hinaus; die Trimmbox bleibt exakt der gewählte Ausschnitt. Der Abstand zwischen zwei Bildern ist immer ≥ 2 × Beschnittzugabe. - Platzierung: gleich große Bilder → exaktes Raster; gemischte Größen → MaxRects-Packer mit fester Ausrichtung je Format (probiert alle Ausrichtungs-Kombinationen und nimmt die mit den wenigsten Bogen). - Die PDF-Seite hat exakt das Bogenmaß. Beim Drucken „Tatsächliche Größe / 100 %" wählen — nicht „an Seite anpassen". - POST /api/print/single — ein Bild exakt auf Maß. Body: { src:{kind:'upload',path}|{kind:'item',id}, crop?:{x,y,w,h} (relativ 0..1; ohne Angabe mittiger Ausschnitt), size|wMm+hMm, landscape?, dpi?, ext?(jpg|png), bleedMm? }. Antwort: die Bilddatei. Header: X-Klarbild-Px, X-Klarbild-Real-Dpi, X-Klarbild-Dpi-Ok. - GET /api/print/single?size=12x15&dpi=300 — nur rechnen: mm → Pixel. - POST /api/print/sheet — Druckbogen als PDF. Body: { paper:{id}|{size}|{wMm,hMm}, landscape?, marginMm?, gapMm?, bleedMm?, center?, dpi?, ext?, footer?, marks:{mode,lengthMm?,offsetMm?}, cells:[{ id, src, crop?, size|wMm+hMm, landscape?, count?, allowRotate? }] }. Antwort: application/pdf. Header: X-Klarbild-Pages, X-Klarbild-Per-Sheet. - GET/POST/DELETE /api/print/presets — Bogen-Vorlagen (Papier, Marken, Formate, Stückzahlen). Mitgeseedet: „Kita-Satz (A4)", „Schulsatz klein (A4)", „Passbildbogen 35×45 (A4)", „2 × 10×7,5 auf Fotopapier 10×15". Eine Vorlage mit mehreren Formaten und nur einem Bild klont das Bild in alle Formate. - Bogen ausliefern: \`deliver: { target: ''|'nas'|, gallery? }\` in /api/print/sheet legt das PDF zusätzlich ins Ziel. Antwort bleibt das PDF; Header X-Klarbild-Delivered (0|1) und X-Klarbild-Delivery-Msg (URI-kodiert). ## MCP-Server (für Assistenten) Werkzeug \`klarbild\` (mcp/klarbild-mcp.mjs), nutzt denselben API-Token: - list_recipes — verfügbare Rezepte. - process_images — Bilder (lokaler Ordner / URLs) mit einem Rezept verarbeiten lassen. - job_status — Fortschritt/Ergebnis eines Auftrags abfragen. - exact_size — OHNE KI: ein Bild exakt auf ein Maß bringen, Datei lokal speichern. - print_sheet — OHNE KI: Druckbogen (mehrere Bilder × Stückzahl, Schnittmarken) als PDF lokal speichern. ## Auslieferung - Picdrop = SFTP/FTPS-Ziel; Galerie = Unterordner unter dem Basispfad. Voller Pfad = Basisordner + Galerie (wird erst beim Ausliefern zusammengesetzt). Standard-Galerie „POSTER LEA"; „The Frame" → „TheFrame-Backgrounds". - Ausgeliefert wird das Ergebnis im gewählten Dateiformat (output_ext, global oder pro Auftrag) — PNG oder JPG. Freigestellte Motive bleiben PNG. - Optionaler .md-Metadaten-Beileger je Ziel schaltbar (Picdrop/NAS/Zusatzziel). ## Datenschutz - Private Session (job.private=true): kein Bibliothekseintrag, keine Auslieferung/Sicherung, kein gespeicherter Prompt; Ergebnis wird nach kurzer Zeit gelöscht. - Sichtbarkeit global steuerbar (nur eigene / alle sehen alles); Admin sieht alles. Weitere Doku (menschlich): In-App /anleitung und /changelog. `; export const GET: APIRoute = async () => new Response(BODY, { headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'public, max-age=3600' } });