o
    Ū9j                     @  sV  d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZ ddlmZ ddlmZ ddlmZ d	d
lmZmZmZmZmZmZmZmZmZmZ edddZejedgdgdgd e ddd Z!e"ddd Z#e"ddd Z$e"ddd Z%e"ddd Z&e'ddRd!d"Z(e"d#d$d% Z)e'd&dRd'd(Z*e"d)d*d+ Z+e"d,d-d. Z,e"d/d0d1 Z-e'd2d3d4 Z.e"d5d6d7 Z/e'd8e
d9fdSd<d=Z0dTd@dAZ1e'dBe
d9e	d9fdUdEdFZ2e'dGe
d9e
d9fdVdIdJZ3ej4dKee5ej6dLdCdM ej4dNee5ej7dOdPdQdM dS )Wu   Plappi-MVP API.

Das eigentliche Produkt-„Gehirn". Clients (heute Handy-PWA, morgen Raspberry Pi)
sprechen NUR mit diesem Backend über /api/turn — Mikro rein, ASR -> Dialog -> TTS,
Audio raus. Der Client bleibt dumm; alle Intelligenz lebt hier.
    )annotationsN)Path)FastAPIFileFormRequest
UploadFile)CORSMiddleware)JSONResponse)StaticFiles   )
animalsasrconfigdialogprofilesessionsstoriesstorettsvoicesz
Plappi MVPz0.1.0)titleversion*)allow_originsallow_methodsallow_headershttpc                   sB   || I dH }| j j}|dks|drd|jd< d|jd< |S )uY   HTML/JS/Manifest nie cachen → Frontend-Updates kommen sofort an (kein „App updaten").N/)z.htmlz.jsz.webmanifestz.no-store, no-cache, must-revalidate, max-age=0zCache-Controlzno-cachePragma)urlpathendswithheaders)request	call_nextrespp r(   //home/nk/hobo-godmode/plappi-mvp/backend/app.py_no_cache_static   s   

r*   z/api/healthc                   C  s$   dt t jt t jt jt jdS )NT)ok
child_langtarget_langvoicemodel)r   	lang_name
CHILD_LANGTARGET_LANGPLAPPI_VOICEDIALOG_MODELr(   r(   r(   r)   health%   s   

r5   z/api/clientconfigc                  C  s   t  } t j| d< | S )Nagent_id)r   client_configELEVENLABS_AGENT_ID)cfgr(   r(   r)   clientconfig0   s   
r:   z
/api/agentc                   C  s$   t jt t jt t jt dS )N)r6   r,   r-   r   )r   r8   r0   r1   r2   r   get_profiler(   r(   r(   r)   agent7   s
   

r<   z/api/profilec                   C     t  S N)r   r;   r(   r(   r(   r)   r;   ?      r;   r$   r   c                   s   |   I d H }t|S r>   )jsonr   save_profiler$   datar(   r(   r)   set_profileD   s   
rD   z/api/voicesc                   C  r=   r>   )r   list_voicesr(   r(   r(   r)   
get_voicesJ   r?   rF   z
/api/voicec                   s"   |   I d H }t|ddS )Nvoice_id )r@   r   
set_activegetrB   r(   r(   r)   	set_voiceO   s   rK   z/api/curriculumc                   C  s   dd t j D t jdS )Nc                 S  s    i | ]\}}|d d |D qS )c                 S  s   g | ]	\}}||d qS ))srder(   ).0rL   rM   r(   r(   r)   
<listcomp>W   s    z)curriculum.<locals>.<dictcomp>.<listcomp>r(   )rN   twordsr(   r(   r)   
<dictcomp>W   s    zcurriculum.<locals>.<dictcomp>)themessensitive_presets)r   
CURRICULUMitemsSENSITIVE_PRESETSr(   r(   r(   r)   
curriculumU   s
   rX   z/api/storiesc                   C     dt  iS )Nr   )r   list_storiesr(   r(   r(   r)   get_stories\      r[   z/api/animalsc                   C  rY   )Nr   )r   list_animalsr(   r(   r(   r)   get_animalsa   r\   r^   z	/api/syncc               
   C  sF   zt  W S  ty" }  ztdt| dddW  Y d } ~ S d } ~ ww )NF)r+   error   )status_code)r   sync	Exceptionr
   strer(   r(   r)   rb   f   s   
"rb   z/api/dashboardc               
   C  sP   z	t   W t  S  ty' }  ztd|  dd W Y d } ~ t  S d } ~ ww )Nz[dashboard] sync failed: T)flush)r   rb   rc   printdashboard_datare   r(   r(   r)   	dashboardn   s   
rj   z
/api/reset.
session_idrd   c                 C  s   t |  ddiS )Nr+   T)r   reset)rk   r(   r(   r)   rl   x   s   
rl   namereturnc                 C  s
   d|  S )Nz/audio/r(   rm   r(   r(   r)   
_audio_url~   s   
rp   z	/api/turnaudior   c           	   	     s   t   }t|jp
djpd}tjt j |  }|	|
 I dH  t|\}}t| |}tj|ddI dH }t| |||t|tt   | d dS )uK   Ein kompletter Gesprächs-Turn: Sprach-Clip -> Plappis gesprochene Antwort.z	clip.webmz.webmNd3l4f3HgkE3P6Fo91lYAr.   i  )rk   
child_textr,   plappi_text	audio_urlms)timer   filenamesuffixr   
UPLOAD_DIRuuiduuid4hexwrite_bytesreadr   
transcriber   respondr   
synthesizer
   rp   int)	rk   rq   t0rz   rawrt   r,   reply
audio_namer(   r(   r)   turn   s    r   z/api/saytextc                   s8   t | |}tj|ddI dH }t| ||t|dS )z;Debug/Test-Pfad ohne Mikro: Text rein -> Dialog + TTS raus.rr   rs   N)rk   rt   ru   rv   )r   r   r   r   r
   rp   )rk   r   r   r   r(   r(   r)   say   s   r   z/audio)	directoryro   r   T)r   htmlweb)r$   r   )rk   rd   )rm   rd   rn   rd   )rk   rd   rq   r   )rk   rd   r   rd   )8__doc__
__future__r   rx   r|   pathlibr   fastapir   r   r   r   r   fastapi.middleware.corsr	   fastapi.responsesr
   fastapi.staticfilesr   rH   r   r   r   r   r   r   r   r   r   r   appadd_middleware
middlewarer*   rJ   r5   r:   r<   r;   postrD   rF   rK   rX   r[   r^   rb   rj   rl   rp   r   r   mountrd   	AUDIO_DIRWEB_DIRr(   r(   r(   r)   <module>   sb    0












	
"