diff --git a/FEATURES.md b/FEATURES.md index 3a5c4da..a9a1d73 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -60,13 +60,38 @@ bis 30.09.: Unterlagen einreichen"*. behalten. Ein Übersetzer sagt dir, was dasteht. BehördenKlar meldet sich von selbst, bevor es zu spät ist. -### 3. Termin in den Kalender — auf einen Tastendruck -`AnalyseScreen` → `terminZumKalender`, inklusive Erinnerung einen Tag vorher. +### 3. Frist und Termin in den Kalender — auch im Web +**App:** `AnalyseScreen` → `terminZumKalender`, auf Tastendruck. -**Bewusst nicht vollautomatisch:** Ungefragt in den Kalender eines Menschen zu -schreiben, wäre übergriffig — und iOS verlangt ohnehin eine Freigabe. Die -*Erinnerungen* laufen automatisch, der *Kalendereintrag* auf Wunsch. +**Web (seit 27.09.):** Nach der Analyse erscheint direkt unter der Frist +„📅 In meinen Kalender eintragen". Der Browser erzeugt eine `.ics`-Datei mit +Frist **und** Termin, jeweils mit Erinnerung **3 Tage und 1 Tag vorher**. Die +Datei entsteht auf dem Gerät und wird **nirgends hochgeladen** — die Erinnerungen +stellt danach der Kalender des Handys selbst. Funktioniert ohne App und ohne Konto. +Details, die schiefgehen können und abgesichert sind: +- Zeilen nach **Bytes** gefaltet (RFC 5545: max. 75), nicht nach Zeichen — + Arabisch/Tigrinya brauchen 2–4 Byte pro Zeichen +- Termin um 23:30 endet korrekt am **nächsten** Tag +- Uhrzeit ohne Zeitzone („Wanduhrzeit") = Ortszeit des Geräts +- Titel und Erinnerungstext ohne deutsche Wörter: Symbol + Datum versteht jeder, + die `aktion` kommt schon in der Sprache des Nutzers + +**Bewusst nicht vollautomatisch:** Ungefragt in einen fremden Kalender zu +schreiben, wäre übergriffig. + +### 3b. Anruf-Hilfe (Web, seit 27.09.) +Die KI liest `kontakt` aus dem Brief — Telefon, Ansprechpartner, Aktenzeichen, +Sprechzeiten — und schreibt einen **Spickzettel** mit 3–5 Sätzen für das Telefonat. + +- Telefonnummer als **Anruf-Knopf** (`tel:`) +- Aktenzeichen **hervorgehoben** — danach wird am Telefon zuerst gefragt +- Jeder Satz **auf Deutsch** (so wird er gesagt) und darunter in der Sprache + des Nutzers (damit er versteht, was er sagt) + +**Regel im Prompt:** Kontaktdaten nur, wenn sie **wörtlich** im Brief stehen. +Getestet mit einem Brief ohne Telefonnummer → `telefon: null`, nichts erfunden. +Eine falsche Nummer wäre schlimmer als keine. ### 4. Ampel statt Datum Rot ≤ 7 Tage, gelb ≤ 21, sonst grün. Die Startseite sortiert nach **Dringlichkeit**, nicht nach Eingang — man sieht sofort, was brennt. diff --git a/proxy/src/index.ts b/proxy/src/index.ts index 6a96ea5..4d466f9 100644 --- a/proxy/src/index.ts +++ b/proxy/src/index.ts @@ -104,6 +104,8 @@ Deine Aufgabe: 4. Erstelle eine konkrete Checkliste, was der Nutzer tun muss. 5. Sei sachlich und beruhigend, nicht alarmierend. +6. Telefonnummern, Namen und Aktenzeichen übernimmst du NUR, wenn sie wörtlich im Brief stehen. Eine erfundene Telefonnummer ist schlimmer als keine — dann null. + Wichtig: Wenn das Bild kein Behördenbrief ist oder unlesbar ist, schreibe das klar in kernaussage und erklaerung_einfach und lasse frist/termin null.`; /** Schlanke Demo-Variante des Analyse-Schemas (ohne Antwort-Optionen — @@ -111,7 +113,7 @@ Wichtig: Wenn das Bild kein Behördenbrief ist oder unlesbar ist, schreibe das k const DEMO_SCHEMA = { type: 'object', additionalProperties: false, - required: ['brieftyp', 'absender', 'kernaussage', 'erklaerung_einfach', 'fachbegriffe', 'frist', 'termin', 'checkliste'], + required: ['brieftyp', 'absender', 'kernaussage', 'erklaerung_einfach', 'fachbegriffe', 'frist', 'termin', 'checkliste', 'kontakt', 'anruf'], properties: { brieftyp: { type: 'string', description: 'Kurze Kategorie des Briefs, z. B. "Einladung Jobcenter".' }, absender: { type: 'string', description: 'Die Behörde, die den Brief geschickt hat.' }, @@ -150,6 +152,28 @@ const DEMO_SCHEMA = { ], }, checkliste: { type: 'array', description: 'To-do-Liste. Leer wenn nichts zu tun ist.', items: { type: 'string' } }, + kontakt: { + description: 'Kontaktdaten aus dem Brief. Jedes Feld NUR, wenn es wörtlich im Brief steht — sonst null. Niemals erfinden.', + type: 'object', additionalProperties: false, + required: ['telefon', 'ansprechpartner', 'aktenzeichen', 'sprechzeiten'], + properties: { + telefon: { description: 'Telefonnummer genau wie im Brief abgedruckt, sonst null.', anyOf: [{ type: 'string' }, { type: 'null' }] }, + ansprechpartner: { description: 'Name der zuständigen Person, sonst null.', anyOf: [{ type: 'string' }, { type: 'null' }] }, + aktenzeichen: { description: 'Aktenzeichen, Kunden-, Steuer- oder BG-Nummer — das, wonach am Telefon gefragt wird. Sonst null.', anyOf: [{ type: 'string' }, { type: 'null' }] }, + sprechzeiten: { description: 'Telefonische Erreichbarkeit laut Brief, sonst null.', anyOf: [{ type: 'string' }, { type: 'null' }] }, + }, + }, + anruf: { + description: 'Spickzettel für einen Anruf bei der Behörde: 3 bis 5 kurze, höfliche Sätze, die man am Telefon sagen kann — Begrüßung, Aktenzeichen nennen, Anliegen, Nachfrage. Leeres Array, wenn ein Anruf nicht sinnvoll ist.', + type: 'array', + items: { + type: 'object', additionalProperties: false, required: ['deutsch', 'bedeutung'], + properties: { + deutsch: { type: 'string', description: 'Der Satz in einfachem Deutsch — genau so wird er am Telefon gesagt.' }, + bedeutung: { type: 'string', description: 'Derselbe Satz in der Sprache des Nutzers, damit er versteht, was er sagt.' }, + }, + }, + }, }, }; @@ -314,7 +338,7 @@ async function demoHandler(request: Request, env: Env): Promise { max_tokens: MAX_TOKENS_OBERGRENZE, system: sprachCode === 'de' ? DEMO_SYSTEM_PROMPT - : `${DEMO_SYSTEM_PROMPT}\n\nWICHTIG — ZIELSPRACHE: Schreibe ALLE Textfelder deiner Antwort auf ${sprachName}, nicht auf Deutsch. Ausnahme: das Feld "begriff" bei fachbegriffe bleibt der deutsche Originalbegriff aus dem Brief (der Nutzer muss ihn im Brief wiederfinden) — nur dessen "erklaerung" wird auf ${sprachName} geschrieben. Datumsangaben bleiben im ISO-Format.`, + : `${DEMO_SYSTEM_PROMPT}\n\nWICHTIG — ZIELSPRACHE: Schreibe ALLE Textfelder deiner Antwort auf ${sprachName}, nicht auf Deutsch. Ausnahme: das Feld "begriff" bei fachbegriffe bleibt der deutsche Originalbegriff aus dem Brief (der Nutzer muss ihn im Brief wiederfinden) — nur dessen "erklaerung" wird auf ${sprachName} geschrieben. Datumsangaben bleiben im ISO-Format. Ebenfalls NICHT übersetzen: das Feld "deutsch" bei anruf (das wird am Telefon auf Deutsch gesagt) und alle kontakt-Felder (sie stehen so im Brief).`, output_config: { format: { type: 'json_schema', schema: DEMO_SCHEMA } }, messages: [ { diff --git a/webseite/demo.html b/webseite/demo.html index b562469..b9f845e 100644 --- a/webseite/demo.html +++ b/webseite/demo.html @@ -159,6 +159,12 @@ /* Ergebnis */ #ergebnis { display: none; } + .anruf-satz { border-inline-start: 3px solid var(--amtsblau); background: #fff; padding: 6px 12px; margin: 10px 0; } + .anruf-de { font-weight: 700; margin: 0; } + .anruf-bed { color: var(--grau); font-size: 15px; margin: 4px 0 0; } + .kontakt-zeile { margin: 6px 0; font-size: 16px; } + .az-wert { font-family: 'Courier New', ui-monospace, monospace; font-weight: 700; background: var(--marker); padding: 1px 6px; } + #ergAnrufKontakt .cta { display: inline-block; width: auto; margin: 4px 0 8px; } .brief-karte { background: #fff; border: 1px solid rgba(33, 33, 29, 0.28); padding: 22px 24px; position: relative; margin-top: 22px; @@ -374,13 +380,23 @@
Brief -

+

+ +
Einfach erklärt -

+

+ +