o
    CH:j%                     @  s   d Z ddlmZ ddlZddlZddlZddlZddlm	Z	 ddl
mZmZ d/d	d
Zd0ddZd1ddZd2ddZd3d4ddZd5d d!Zd5d"d#Zd5d$d%Zd5d&d'Zd1d(d)Zd6d+d,Zd0d-d.ZdS )7u  Das Plappi-Gehirn: bilinguale Sprach-Tutor-Persona.

Heute über die claude-CLI (nutzt das vorhandene Abo). Die Persona +
Sicherheits-Regeln sind das eigentliche Produkt-IP und bleiben gleich,
egal welches Modell darunter läuft — später eine private OSS-EU-Inferenz
(genau das geförderte F&E-Arbeitspaket).

Compliance eingebaut (aus der KS/EU-AI-Act-Recherche): Plappi ist strikt ein
LERNWERKZEUG/Tutor, NIE ein "Freund/Begleiter" — das hält die Kickstarter-Regeln
(Verbot manipulativer Companion-Toys) und den EU AI Act ein.
    )annotationsN)List   )configsessionsreturnstrc                  C  s   t t j} t t j}dg d| d|  d|  d| d| d| d|  d	| d
| d| d| d| d|  d| d| dS )N u  Du bist „Plappi", ein freundliches, geduldiges Sprachlern-Spielzeug für Kinder (2–10 Jahre).
Du bist ein LERNWERKZEUG und Sprach-Tutor — NIEMALS ein „Freund", „Begleiter" oder emotionaler Vertrauter.
Baue keine emotionale Abhängigkeit auf, gib dich nicht als Lebewesen oder echte Person aus,
und sage nichts, was ein Kind manipulieren könnte. (Pflicht: EU-AI-Act + Kindersicherheit.)

Deine Aufgabe: Du hilfst dem Kind spielerisch, u&    zu lernen, während ihr überwiegend u    sprecht.

Regeln:
- Antworte SEHR KURZ: 1–2 einfache Sätze. Deine Antwort wird laut vorgelesen — also gesprochene,
  leichte Sprache. Keine Listen, keine Emojis, keine Sternchen, keine Klammern, keine Sonderzeichen.
- Sprich überwiegend u   . Webe natürliche, GANZE uH   -Brocken ein — Lob,
  Staunen, kleine Spiel-Aufforderungen direkt auf u\    — die Bedeutung muss aus dem
  Zusammenhang/Tonfall klar sein.
- VERBOTEN: ein einzelnes z-Wort mitten in einen u?   -Satz stellen und sofort übersetzen
  („der Hund heißt auf uS    …", „… das ist X"). Das verwirrt und fördert Sprachmischung.
- Wenn du ein u#   -Wort einführst: sag es als ganze u   -Phrase und lade das Kind ein,
  es SELBST zu sagen („Kannst du auch … sagen?"). Das Kind soll das Wort produzieren — dann lobst du.
- Übersetze nicht Wort für Wort und sag NIE Übersetzungs-Formeln wie „das heißt … auf u/   " oder „… bedeutet …". Lieber eine kurze u   -Phrase, dann beiläufig auf z3 weiter.
- In JEDER Antwort mindestens EINE kleine uH   -Phrase einbauen — auch bei Sachfragen — nie eine Antwort ganz ohne u{  .
- Lobe jeden Versuch. Korrigiere sanft und positiv, nie tadelnd.
- Begrüße NUR einmal ganz am Anfang. Beginne NICHT jede Antwort mit „Ćao"/„Zdravo"/dem Namen — steige direkt ins Thema ein, sonst wirkt es wie eine Schleife.
- Bleib kindgerecht. Keine Angst-, Gewalt-, Werbe- oder Erwachsenenthemen.
- Frage NIE nach persönlichen Daten (Name, Adresse, Schule, Telefon).
- Bei Gefühlen/heiklen Themen (Angst, Trauer, Familie): erkenne das Gefühl ZUERST warm an
  („oh, das tut mir leid", „das ist nicht schön"), tröste kurz, und schlage sanft vor, mit Mama oder
  Papa darüber zu reden. Sag NIE „ich kann dir nicht helfen". Dann behutsam zurück ins Spiel.
- Sei fröhlich, neugierig, ermutigend. Stelle kleine, einfache Fragen, damit das Kind selbst spricht.

Gib NUR Plappis gesprochene Antwort aus — keine Bühnenanweisungen, keine Anführungszeichen, kein Vorspann.)r   	lang_name
CHILD_LANGTARGET_LANGjoin)childtarget r   2/home/nk/hobo-godmode/plappi-mvp/backend/dialog.py_persona   sB   


r   
session_id
child_textc                 C  sv   t | tj}g }|D ]}|d dkrdnd}|| d|d   qd|}|r1d| d	 nd
}| d| dS )Nroler   KindPlappiz: text
u   Bisheriges Gespräch:
z

r	   zDas Kind sagt jetzt: "z"
Antworte als Plappi.)r   recentr   HISTORY_TURNSappendr   )r   r   turnslinestwhoconvoheadr   r   r   _build_prompt9   s   
r#   promptpersonac              	   C  s   t jd| d|dt jg}|g d |ddg |g}|D ]3}z(tj|ddt jtt jd}|jp/d		 }|j
d
krC|rC|dsC|W   S W q tyM   Y qw d	S )Nz-pz--append-system-promptz--model)--output-formatr   z--strict-mcp-configz--mcp-configz{"mcpServers":{}}r&   r   T)capture_outputr   timeoutcwdr	   r   zError:)r   
CLAUDE_CLIDIALOG_MODEL
subprocessrunDIALOG_TIMEOUTr   	BRAIN_CWDstdoutstrip
returncode
startswith	Exception)r$   r%   baseattemptscmdroutr   r   r   _call_claudeD   s*   



r:   namec                 C  s   t j| }|r| S z2tjd }| r9|jdd D ]}| }|	| d r8|
ddd    W S qW dS W dS  tyH   Y dS w )uZ   Key aus Umgebung ODER aus plappi-mvp/.keys (KEY=VALUE pro Zeile) — ohne Server-Neustart.z.keyszutf-8)encoding=r   r	   )osenvirongetr1   r   BASE_DIRexists	read_text
splitlinesr3   splitr4   )r;   vfliner   r   r   _api_keyZ   s&   
rI      urlpayloaddictheadersr(   intc                 C  s   t jj| t| dd}| D ]
\}}||| qt jj||d}t	|
  W  d    S 1 s9w   Y  d S )NPOST)datamethod)r(   )urllibrequestRequestjsondumpsencodeitems
add_headerurlopenloadsreaddecode)rK   rL   rN   r(   reqkrF   r8   r   r   r   
_post_jsonk   s   $ra   keyc                 C  sx   t jdd}d| d| }dd|igidd| igdgd	d
dd}t||ddi}|d d d d d d  S )NPLAPPI_GEMINI_MODELzgemini-2.5-flashz8https://generativelanguage.googleapis.com/v1beta/models/z:generateContent?key=partsr   user)r   rd   ffffff?   )temperaturemaxOutputTokens)systemInstructioncontentsgenerationConfigContent-Typeapplication/json
candidatesr   contentr>   r?   r@   ra   r1   )r$   r%   rb   modelrK   bodydr   r   r   _geminis   s    ru   c                 C  sX   t jdd}|d|d| dgd}td||dd	d
}ddd |dg D  S )NPLAPPI_ANTHROPIC_MODELzclaude-3-5-haiku-latestrg   re   r   rp   )rr   
max_tokenssystemmessagesz%https://api.anthropic.com/v1/messagesz
2023-06-01rn   )z	x-api-keyzanthropic-versionrm   r	   c                 s  s    | ]	}| d dV  qdS )r   r	   N)r@   ).0pr   r   r   	<genexpr>   s    z_anthropic.<locals>.<genexpr>rp   )r>   r?   r@   ra   r   r1   r$   r%   rb   rr   rs   rt   r   r   r   
_anthropic}   s   

 r   c                 C  sZ   t jdd}|ddd|dd| dgd}td	|d
| dd}|d d d d  S )NPLAPPI_OPENAI_MODELzgpt-4o-minirg   rf   ry   rw   re   rr   rx   rh   rz   z*https://api.openai.com/v1/chat/completionsBearer rn   )Authorizationrm   choicesr   messagerp   rq   r~   r   r   r   _openai   s   r   c                 C  s^   t jdd}|ddd|dd| dgd}td	|d
| dddd}|d d d d  S )NPLAPPI_OPENROUTER_MODELzgoogle/gemini-2.5-flashi@  rf   ry   rw   re   r   z-https://openrouter.ai/api/v1/chat/completionsr   rn   zhttps://plappi.localr   )r   rm   zHTTP-RefererzX-Titler   r   r   rp   rq   r~   r   r   r   _openrouter   s   r   c              
   C  s   t d}t dpt d}t d}t d}z'|rt| ||W S |r't| ||W S |r0t| ||W S |r9t| ||W S W dS  tyX } ztd| ddd	 W Y d
}~dS d
}~ww )uj   Schnelles Gehirn über eine externe API, sobald ein Key da ist (OpenRouter > Gemini > Anthropic > OpenAI).OPENROUTER_API_KEYGEMINI_API_KEYGOOGLE_API_KEYANTHROPIC_API_KEYOPENAI_API_KEYz[dialog] API-Brain Fehler (z) -> Claude-CLI FallbackT)flushNr	   )rI   r   ru   r   r   r4   print)r$   r%   orkgkakoker   r   r   	_call_api   s(   r   r   c                 C  s   d|  dS )Nz6Hallo, ich bin Plappi. Lass uns zusammen ein Wort auf z% lernen. Sag mir, was du gerne magst.r   )r   r   r   r   	_fallback   s   r   c                 C  sj   |pd  }|rt| d| t| |}nd}t }t||p+t||p+tt	tj
}t| d| |S )zDLiefert Plappis Antworttext und schreibt beide Turns in die Session.r	   r   uz   Das Kind hat noch nichts gesagt oder war still. Begrüße es kurz als Plappi und lade es zu einem kleinen Sprachspiel ein.plappi)r1   r   add_turnr#   r   r   r:   r   r   r
   r   )r   r   r$   r%   replyr   r   r   respond   s   $r   )r   r   )r   r   r   r   r   r   )r$   r   r%   r   r   r   )r;   r   r   r   )rJ   )
rK   r   rL   rM   rN   rM   r(   rO   r   rM   )r$   r   r%   r   rb   r   r   r   )r   r   r   r   )__doc__
__future__r   rV   r>   r,   urllib.requestrS   typingr   r	   r   r   r   r#   r:   rI   ra   ru   r   r   r   r   r   r   r   r   r   r   <module>   s(    

"





	
	

