+
    ]Qj                     F   ^ RI HtHtHtHtHt ^ RIHt ^ RIH	t	 ^RI
Ht ^RIHt ^RIHtHtHtHtHtHtHtHt ^RIHtHtHtHt ]! RR	R
7      t]! RR7      3R R llt]P=                  ]4      R R l4       t]P=                  ]4      R R l4       t ]PC                  R4      R R l4       t"]PC                  R4      R R l4       t#]PC                  R]! ]4      .R7      R R l4       t$]PK                  R]! ]4      .R7      R-R R ll4       t&]PK                  R ]]! ]4      .R!7      R" R# l4       t']PK                  R$]]! ]4      .R!7      R% R& l4       t(]PK                  R']]! ]4      .R!7      R( R) l4       t)]PK                  R*]]! ]4      .R!7      R+ R, l4       t*R# ).    )DependsFastAPIHeaderHTTPExceptionRequest)ResponseValidationError)JSONResponse)settings)LLMGenerationError)GenerateItineraryRequestGenerateItineraryResponseRecommendStayRequestRecommendStayResponseSuggestQuestionsRequestSuggestQuestionsResponseSuggestResponseRequestSuggestResponseResponse)	itinerary	questionsreplystayzmeridian-aiz0.1.0)titleversionN)defaultc                6    V ^8  d   QhR\         R,          RR/# )   authorizationNreturn)str)formats   "0C:\xampp\htdocs\meridian\meridian-ai\app\main.py__annotate__r"      s"     X Xt Xt X    c                    \         P                  '       g   R# V R\         P                   28w  d   \        RRR7      hR# )a  Baseline service-to-service auth. Meridian-Backend authenticates with a shared
bearer token - never the end user's own frontend session token, which this
service never sees and has no way to validate (see README.md 4.1 for why that
split matters). This is the simple half of that section's design; swap the token
comparison below for the signed-request-with-nonce scheme described there if a
static shared secret ever stops being a strong enough guarantee.
NzBearer i  z Invalid or missing service token)status_codedetail)r
   service_tokenr   )r   s   &r!   require_service_tokenr(      s<     !!!'("8"8!9::4VWW ;r#   c                <    V ^8  d   QhR\         R\        R\        /# r   _requestexcr   )r   r   r	   )r    s   "r!   r"   r"   %   s"      ' 8J | r#   c           
      T    \        R RRRRVP                  RVP                  //R7      # )  errorcodeLLM_GENERATION_FAILEDmessagedetailsr%   content)r	   r2   r&   r+   r,   s   &&r!   handle_llm_generation_errorr7   $   s4    6#:Is{{T]_b_i_ijk r#   c                <    V ^8  d   QhR\         R\        R\        /# r*   )r   r   r	   )r    s   "r!   r"   r"   -   s#      w =T Ye r#   c                 >    \        R RRRRRR\        V4      //R7      # )r.   r/   r0   LLM_RESPONSE_INVALIDr2   z-Model output did not match the expected shaper3   r4   )r	   r   r6   s   &&r!    handle_response_validation_errorr;   ,   sI     6#99Fu  xA  CF  GJ  CK  L  M r#   z/modelsc                $    V ^8  d   QhR\         /# r   r   dict)r    s   "r!   r"   r"   9   s     M M Mr#   c                 @    ^RI Hp  RV ! 4       R\        P                  /# )u   Returns available LLM providers and their models. No auth required — the
frontend reads this to populate the model selector in the generate-itinerary modal.
list_providers	providersr   )providers.factoryrB   r
   llm_providerrA   s    r!   modelsrF   8   s    
 2)9h6K6KLLr#   z/healthc                $    V ^8  d   QhR\         /# r=   r>   )r    s   "r!   r"   r"   B   s       r#   c                  t    ^RI Hp  V ! 4       pRRR\        P                  RVP                  RVP
                  /# )   get_providerstatusokprimary_provideractive_providersexhausted_providers)rD   rK   r
   rE   active	exhaustedrK   ps     r!   healthrU   A   s8    /A$H11AHHq{{	 r#   z/providers/status)dependenciesc                $    V ^8  d   QhR\         /# r=   r>   )r    s   "r!   r"   r"   N   s      $ r#   c                 h    ^RI Hp  V ! 4       pRVP                  RVP                  RVP                  /# )zFShows which providers are active and which have been marked exhausted.rJ   
configuredrQ   rR   )rD   rK   namesrQ   rR   rS   s     r!   providers_statusr[   M   s3     0Aagg!((Q[[ r#   z/providers/resetc                >    V ^8  d   QhR\         R,          R\        /# )r   nameNr   )r   r?   )r    s   "r!   r"   r"   Z   s     8 8#* 8 8r#   c                r    ^RI Hp V! 4       pVP                  V 4       RT ;'       g    RRVP                  /# )zClears exhausted state so a topped-up provider is tried again.
Pass ?name=openai to reset just one, or call with no param to reset all.
rJ   resetallrQ   )rD   rK   r_   rQ   )r]   rK   rT   s   &  r!   providers_resetra   Y   s2    
 0AGGDMT]]UHahh77r#   z/generate_itinerary)response_modelrV   c                0    V ^8  d   QhR\         R\        /# r   payloadr   )r   r?   )r    s   "r!   r"   r"   i   s     1 1)A 1d 1r#   c                 .    \         P                  ! V 4      # N)r   generate_itineraryre   s   &r!   generate_itinerary_endpointrj   d   s     ''00r#   z/suggest_responsec                0    V ^8  d   QhR\         R\        /# rd   )r   r?   )r    s   "r!   r"   r"   r   s     + +'= +$ +r#   c                 .    \         P                  ! V 4      # rg   )r   suggest_responseri   s   &r!   suggest_response_endpointrn   m   s     !!'**r#   z/recommend_stayc                0    V ^8  d   QhR\         R\        /# rd   )r   r?   )r    s   "r!   r"   r"   {   s     ( (%9 (d (r#   c                 .    \         P                  ! V 4      # rg   )r   recommend_stayri   s   &r!   recommend_stay_endpointrr   v   s     w''r#   z/suggest_questionsc                0    V ^8  d   QhR\         R\        /# rd   )r   r?   )r    s   "r!   r"   r"      s     0 0(? 0D 0r#   c                 .    \         P                  ! V 4      # rg   )r   suggest_questionsri   s   &r!   suggest_questions_endpointrv      s     &&w//r#   rg   )+fastapir   r   r   r   r   fastapi.exceptionsr   fastapi.responsesr	   configr
   
exceptionsr   schemasr   r   r   r   r   r   r   r   servicesr   r   r   r   appr(   exception_handlerr7   r;   getrF   rU   r[   postra   rj   rn   rr   rv    r#   r!   <module>r      s   D D 6 *  *	 	 	 8 7M73 7=T6J X )* + ./ 0 M M   	G4I,J+KL M 
G4I,J+KL8 M8 ,/01 
 
1
1 */01 
 
+
+ (/01 
 
(
( +/01 
 
0
0r#   