+
    jHàjÞ©  ã                   óh	  a € Rì tˆ0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIHt ^ RIHtHtHt ^ RIHtHtHtHtHtHt ^ RIH t H!t! ^ RI"H#t# ^ RI$H%t%H&t& ^ R	I'H(t( ^ R
I)H*t*H+t+H,t,H-t-H.t.H/t/H0t0H1t1 ^ RI2H3t3H4t4H5t5H6t6H7t7 ]! 4       t8](! RR4      t9](! RR4      t:](! RR4      t;](! RR4      t<](! R4      t=RRRRRRRRRRRRRRR R!/t>Rít?]@! 0 Rîm4      tA0 RïmtB]@! 0 Rðm4      tC]@! R-R.04      tDR/ R0 ltER1 R2 ltFRñtGRòtHRótI/ R3R4bR5R6bR7R8bR9R:bR;R<bR=R>bR?R@bRAR4bRBR8bRCRDbRERFbRGRHbRIRJbRKRLbRMRNbRORPbRQRRbRSRHRTRURVRWRXRYRZR[R\R]RR^R_R`RaRbRcRdReRfRgR^RhRiRjRiRkR[/CtJ/ R"RlbRRbR#RmbRRbRRbRRbR$RnbR%RobR&RpbR'RqbR(RrbR)RsbR*RtbRRbRRbR+RubR,RvbRR/CtKRw Rx ltLRy Rz ltM]Pœ                  R{ R| l4       tORôR} R~ lltPRôR R€ lltQ]Pœ                  R� R‚ l4       tRRƒ R„ ltSRôR… R† lltTR‡ Rˆ ltUR‰ RŠ ltVR‹ RŒ ltWRôR� RŽ lltXR� R� ltYR‘ R’ ltZR“ R” lt[]8P¹                  R•4      R– R— l4       t]Rõt^R˜t_R™ Rš lt`]8P¹                  R›4      Rœ R� l4       taRž RŸ ltbRítc]@! 0 Röm4      tdR÷te] ^ k R  R¡ ltfR¢ R£ ltgR¤ R¥ lth]8PÓ                  R¦4      RôR§ R¨ ll4       tj]8P¹                  R©4      RôRª R« ll4       tkR¬ R­ ltlR® R¯ ltm]8P¹                  R°4      R± R² l4       tnR³R´/Rµ R¶ llto]8P¹                  R·4      R¸ R¹ l4       tp]8P¹                  Rº4      ]8Pã                  Rº4      R» R¼ l4       4       trR½ R¾ ltsR¿ RÀ ltt]8PÓ                  RÁ4      RÂ RÃ l4       tuRÄ RÅ ltv]8PÓ                  RÆ4      ]! RÇ4      ]! RÇ4      ]! RÈ4      3RÉ RÊ ll4       tw]8PÓ                  RË4      RÌ RÍ l4       tx]8Pó                  R©4      RÎ RÏ l4       tz]{RÐ3]|RÑ3]}RÒ33t~]8P¹                  RÓ4      RôRÔ RÕ ll4       t]8P¹                  RÖ4      RøR× RØ ll4       t€]8PÓ                  RÙ4      RôRÚ RÛ ll4       t�RÜ RÝ lt‚RÞ Rß ltƒ]8P¹                  Rà4      RøRá Râ ll4       t„]8P¹                  Rã4      RùRä Rå ll4       t…]8P¹                  Ræ4      RôRç Rè ll4       t†]8P¹                  Ré4      RôRê Rë ll4       t‡R# )úzÊManaged-files, chat image upload, /api/media and /api/fs dashboard routes.

Helpers/state that tests monkeypatch on ``web_server`` stay there and are
reached through the late-binding seam (cycle-safe).
N)Údatetime©ÚPath)ÚAnyÚDictÚOptional)Ú	APIRouterÚFileÚFormÚHTTPExceptionÚRequestÚ
UploadFile)ÚFileResponseÚStreamingResponse)Úwindows_hide_flags)ÚLiveConnectionErrorÚoffline_file_access)Úlate)ÚSANDBOX_NOT_FOUNDÚ_agent_fs_pathÚ_fs_pathÚ_hosted_fs_read_guardÚ_is_unmapped_container_pathÚ_managed_file_entryÚ_managed_response_metaÚ_resolve_managed_path)ÚChatImageUploadÚFsWriteTextÚManagedDirectoryCreateÚManagedFileDeleteÚManagedFileUploadÚ_profile_scopezhermes_cli.web_server_profilesÚget_hermes_homezhermes_cli.configÚload_configÚload_envÚ_require_tokenú.pngz	image/pngú.jpgz
image/jpegú.jpegú.gifz	image/gifú.webpz
image/webpz.svgzimage/svg+xmlú.bmpz	image/bmpz.icozimage/x-iconú.aviú.flacú.m4aú.mkvú.movú.mp3ú.mp4ú.oggú.opusú.wavú.webmz
mcp-tokensÚpairingc                ó0   € V ^8„  d   QhR\         R\        /# )é   ÚnameÚreturn©ÚstrÚbool)Úformats   "ÚA/home/ubuntu/.hermes/hermes-agent/hermes_cli/web_routers/files.pyÚ__annotate__rA   V   s   € ÷ 8ñ 8¤ð 8¬ñ 8ó    c                ó‚   € V P                  4       pVR8X  g   VP                  R4      '       g   VR8X  d   R# V\        9   # )u"  Basename denylist: ``.env`` / ``.env.<suffix>`` / ``.envrc`` plus the
credential-store basenames. Case-insensitive so ``.ENV`` / ``Auth.JSON``
on case-insensitive mounts can't slip past. Basename-only â€” call sites use
:func:`_is_sensitive_path`, which adds the credential-directory check.z.envz.env.z.envrcT)ÚlowerÚ
startswithÚ!_SENSITIVE_MANAGED_FILE_BASENAMES)r:   Úlowereds   & r@   Ú_is_sensitive_filenamerH   V   s=   € ð
 �j‰j‹l€GØ�&Ô˜G×.Ñ.¨w×7Ò7¸7ÀhÔ;NÙØÔ7Ñ7Ð7rB   c                ó0   € V ^8„  d   QhR\         R\        /# ©r9   Úpathr;   )r   r>   )r?   s   "r@   rA   rA   a   s   € ÷ Tñ TœTð T¤dñ TrB   c                óÌ   € \        V P                  4      '       d   R# \        ;QJ d&    R V P                   4       F  '       g   K   R# 	  R# ! R V P                   4       4      # )a°  True when the basename is sensitive OR any path component (case-
insensitive) is a credential directory. Read-side guard (list/read/
download); the write endpoints are a separate threat class.

Read-side only: this guards list/read/download (the #57505 exfil surface). The write endpoints
(upload/mkdir/delete) are a separate threat class handled by the write-path checks; extending this guard
to them is out of scope for this fix.
Tc              3   óN   "  € T F  qP                  4       \        9   x € K  	  R # 5i©N)rD   Ú_SENSITIVE_MANAGED_DIR_NAMES)Ú.0Úparts   & r@   Ú	<genexpr>Ú%_is_sensitive_path.<locals>.<genexpr>l   s   é € ÐSÉ
À�z‰z‹|Ô;Ö;Ë
ùs   ‚#%F)rH   r:   ÚanyÚparts)rK   s   &r@   Ú_is_sensitive_pathrV   a   sG   € ô ˜dŸi™i×(Ò(Ùß‹3ÑSÈÏ
Ê
ÓS�3Œ3ÐSŠ3ÐSˆ3ÑSÈÏ
Ê
ÓSÓSÐSrB   z.cÚcz.confÚiniz.cppÚcppz.cssÚcssz.csvÚcsvz.goÚgoz.graphqlÚgraphqlz.hz.hppz.htmlÚhtmlz.javaÚjavaz.jsÚ
javascriptz.jsonÚjsonz.jsxÚjsxz.ktÚkotlinz.luaÚluaz.mdÚmarkdownz.mjsz.pyÚpythonz.rbÚrubyz.rsÚrustz.shÚshellz.sqlÚsqlÚxmlz.tomlÚtomlz.tsÚ
typescriptz.tsxÚtsxz.txtÚtextz.xmlz.yamlÚyamlz.ymlz.zshzvideo/x-msvideoz
audio/flacz	audio/mp4zvideo/x-matroskazvideo/quicktimez
audio/mpegz	video/mp4z	audio/oggzaudio/ogg; codecs=opusz	audio/wavz
video/webmc                ó0   € V ^8„  d   QhR\         R\        /# rJ   ©r   r=   )r?   s   "r@   rA   rA   ‡   s   € ÷ 1ñ 1œð 1¤ñ 1rB   c                 óÀ   € V P                   P                  4       pV\        9   d   \        V,          # \        P                  ! \        V 4      4      w  r#T;'       g    R # )úapplication/octet-stream)ÚsuffixrD   Ú_FS_MIME_TYPESÚ	mimetypesÚ
guess_typer=   )rK   ru   ÚguessedÚ_s   &   r@   Ú_fs_mime_typer{   ‡   sL   € Ø�[‰[×ÑÓ €FØ”ÔÜ˜fÕ%Ð%Ü×%Ò%¤c¨$£iÓ0�J€GØ×0Ð0Ð0Ð0rB   c                ó0   € V ^8„  d   QhR\         R\        /# )r9   Údatar;   )Úbytesr>   )r?   s   "r@   rA   rA   �   s   € ÷ )ñ )œ5ð )¤Tñ )rB   c                 óv   € V '       g   R # RV 9   d   R# \        R V  4       4      pV\        V 4      ,          R8„  # )Fó    Tc              3   óH   "  € T F  q^ 8  g   K  VR9  g   K  ^x € K  	  R# 5i)é    N>   é	   é
   é   © )rP   Úbytes   & r@   rR   Ú#_fs_looks_binary.<locals>.<genexpr>”   s   é € ÐQ¡4˜4°"©9”Q¸À[Ñ9P—Q’Q£4ùs   ‚"�"˜
"g¸…ëQ¸¾?)ÚsumÚlen)r}   Ú
suspiciouss   & r@   Ú_fs_looks_binaryrŒ   �   s6   € ßÙØ�„}ÙÜÑQ¡4ÓQÓQ€JØœ˜D›	Õ! DÑ(Ð(rB   c                ó0   € V ^8„  d   QhR\         R\         /# )r9   ÚdeniedÚfailed©r=   )r?   s   "r@   rA   rA   ™   s   € ÷ Hñ H”sð H¤Cñ HrB   c              #  ó�   "  €  Rx € R#   \          d    \        RT R7      h\         d   p\        RT RT 2R7      hRp?ii ; i5i)zNPermissionError -> 403 ``denied``; other OSError -> 500 ``"<failed>: <exc>"``.Né“  ©Ústatus_codeÚdetailéô  ú: )ÚPermissionErrorr   ÚOSError)rŽ   r�   Úexcs   && r@   Ú
_io_errorsr›   ˜   sL   é € ðHÝøÜô <Ü¨°FÔ;Ð;Üô HÜ¨°v°h¸bÀÀÐ4FÔGÐGûðHüs'   ‚A„
 ˆAŠ A«A¬>¾AÁAc                óR   € V ^8„  d   QhR\         R\        \         ,          R\        /# ©r9   rK   Úprofile_homer;   )r   r   r=   )r?   s   "r@   rA   rA   £   s&   € ÷ ?ñ ?¤tð ?¼8ÄD½>ð ?ÔUXñ ?rB   c                óX   € \        V P                  4       VR7      pV'       d   \        # R# )zIDistinguish an untranslated agent-sandbox path from a plain missing file.©rž   úFile not found)r   Úas_posixr   )rK   rž   Úunmappeds   && r@   Ú_fs_sandbox_not_found_detailr¤   £   s#   € ä*¨4¯=©=«?ÈÔV€Hß (ÔÐ>Ð.>Ð>rB   c                óˆ   € V ^8„  d   QhR\         R\        \         ,          R\        \         \        P                  3,          /# r�   )r   r   ÚtupleÚosÚstat_result)r?   s   "r@   rA   rA   ©   s6   € ÷ ñ œ4ð ¬x¼­~ð ÌÌtÔUW×UcÑUcÐOcÕIdñ rB   c                 ó:  € \        \        V 4      4      p VP                  4       p\        P                  ! TP                  4      '       d   \        RRR7      h\        P                  ! TP                  4      '       g   \        RRR7      h\        T4      '       d   \        RR	R7      hY#3#   \        \        3 d    \        R \        Y!4      R7      h\         d    \        RRR7      h\         d&   p\        R\        T4      ;'       g    RR7      hRp?ii ; i)
é”  r“   r’   úFile is not readableé�  úInvalid pathNúPath points to a directoryúOnly regular files can be readú(Access to sensitive files is not allowed)r   r=   ÚstatÚFileNotFoundErrorÚNotADirectoryErrorr   r¤   r˜   r™   ÚS_ISDIRÚst_modeÚS_ISREGrV   )rK   rž   ÚtargetÚstrš   s   &&   r@   Ú_fs_regular_filer¹   ©   sí   € Ü”c˜$“iÓ €FðPØ�[‰[‹]ˆô ‡|‚|�B—J‘J×ÒÜ¨Ð4PÔQÐQÜ�<Š<˜Ÿ
™
×#Ò#Ü¨Ð4TÔUÐUÜ˜&×!Ò!Ü¨Ð4^Ô_Ð_Øˆ:Ðøô Ô1Ð2ô hÜ¨Ô4PÐQWÓ4fÔgÐgÜô LÜ¨Ð4JÔKÐKÜô PÜ¨´C¸³H×4NÐ4NÀÔOÐOûðPús#   –B- Â-/DÃDÃ4DÃ5 DÄDc                ó$   € V ^8„  d   QhR\         /# )r9   r·   r   )r?   s   "r@   rA   rA   ½   s   € ÷ 	Gñ 	Gœ4ñ 	GrB   c              #  óÐ   "  €  \        V RR7      ;_uu_ 4        Rx € RRR4       R#   + '       g   i     R# ; i  \         d   p\        R\        T4      R7      ThRp?ii ; i5i)zÕHold ``offline_file_access`` for serving ``target``; 409 while a SQLite connection to it is live.

Callers keep the block open through the file's close: a raw close cancels this process's
SQLite POSIX locks on it.Úserve)ÚwhatNé™  r“   )r   r   r   r=   )r·   rš   s   & r@   Ú_serve_offliner¿   ¼   sM   é € ðGÜ  ¨g×6Ö6Û÷ 7×6×6Ò6ûäô GÜ¨´C¸³HÔ=À3ÐFûðGüs>   ‚A&„< ™(ž< ¦A&¨9	³< ·A&¹< ¼A#ÁAÁA#Á#A&c                ó(   € V ^8„  d   QhR\         RR/# )r9   r·   r;   Nr   )r?   s   "r@   rA   rA   É   s   € ÷ 	ñ 	¤$ð 	¨4ñ 	rB   c                óh   € \        V 4      ;_uu_ 4         RRR4       R#   + '       g   i     R# ; i)aÎ  Point-in-time 409 before streaming ``target`` while a SQLite connection to it is live.

``FileResponse`` opens and closes the file in-process, and that raw close cancels the
connection's POSIX locks. The registry lock can't be held across a streamed response
(never across an await/yield), so streamed routes only get this admission check. It
takes the global registry lock, which other threads hold across whole-file reads, so
call it via ``asyncio.to_thread``.N)r¿   ©r·   s   &r@   Ú_refuse_live_databaserÃ   É   s!   € ô 
˜×	Õ	Ø÷ 
 ×	×	Ò	ús   ”  1	c                óR   € V ^8„  d   QhR\         R\        \        ,          R\        /# )r9   r·   Úlimitr;   )r   r   Úintr~   )r?   s   "r@   rA   rA   Õ   s*   € ÷ Tñ Tœ4ð T¬´­ð TÄñ TrB   c           	     óÞ  €  \        V 4      ;_uu_ 4        Vf   V P                  4       uuRRR4       # V P                  R4      ;_uu_ 4       pVP                  V4      uuRRR4       uuRRR4       #   + '       g   i     M; i RRR4       R#   + '       g   i     R# ; i  \         d    \        RRR7      h\         d&   p\        R\        T4      ;'       g    RR7      hRp?ii ; i)z_Read (a prefix of) ``target``; 403/400 on failure, 409 while a SQLite connection to it is live.NÚrbr’   r«   r“   r¬   zFile read failed)r¿   Ú
read_bytesÚopenÚreadr˜   r   r™   r=   )r·   rÅ   Úhandlerš   s   &&  r@   Ú_fs_read_bytesrÍ   Õ   sº   € ð	TÜ˜F×#Õ#ØŠ}Ø×(Ñ(Ó*÷ $Ò#ð —‘˜T×"Ô" fØ—{‘{ 5Ó)÷ #Ñ"÷ $Ò#÷ #×"úÐ"÷ $×#×#Ò#ûô
 ô LÜ¨Ð4JÔKÐKÜô TÜ¨´C¸³H×4RÐ4RÐ@RÔSÐSûðTúsb   ‚B% •B©
B% ´BÁA3	Á
BÁ(
B% Á3BÁ>BÂB% ÂB"	ÂB% Â"B% Â% C,ÃC,Ã C'Ã'C,c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r9   Ústartr;   Nrr   )r?   s   "r@   rA   rA   ã   s   € ÷ ñ œTð ¤c¨D¥jñ rB   c                 óÚ   € T p\        ^24       FF  p VR,          P                  4       '       d   \        V4      u #  TP                  pY18X  d    R# TpKH  	  R#   \         d      R# i ; i)é2   ú.gitN)ÚrangeÚexistsr=   r™   Úparent)rÏ   Ú	directoryrz   rÕ   s   &   r@   Ú_fs_find_git_rootr×   ã   sq   € Ø€IÜ�2ŽYˆð	Ø˜FÕ"×*Ñ*×,Ò,Ü˜9“~Ò%ð -ð ×!Ñ!ˆØÔÚØŠ	ñ ñ øô ô 	Ûð	ús   ’'AÁA*Á)A*c                ó$   € V ^8„  d   QhR\         /# ©r9   r;   r�   )r?   s   "r@   rA   rA   ò   s   € ÷ 
ñ 
œñ 
rB   c                  ó  € \        4       P                  R 4      ;'       g    / p \        V P                  R4      ;'       g*    \        P                  P                  R4      ;'       g    R4      P                  4       pV'       dT   VR9  dM    \        V4      P                  4       P                  RR7      pVP                  4       '       d   \        V4      #  \        \        P                  ! 4       4      #   \        \        3 d     L1i ; i)ÚterminalÚcwdÚTERMINAL_CWDÚ F)Ústrict>   Ú.rÜ   Úauto)r#   Úgetr=   r§   ÚenvironÚstripr   Ú
expanduserÚresolveÚis_dirr™   ÚRuntimeErrorrÜ   )Úcfg_terminalÚrawÚ	candidates      r@   Ú_fs_default_cwdrì   ò   sÐ   € Ü“=×$Ñ$ ZÓ0×6Ð6°B€LÜ
ˆl×Ñ˜uÓ%×MÐM¬¯©¯©¸Ó)G×MÐMÈ2Ó
N×
TÑ
TÓ
V€Cß
ˆsÐ.Ô.ð	Ü˜S›	×,Ñ,Ó.×6Ñ6¸eÐ6ÓDˆIØ×Ñ×!Ò!Ü˜9“~Ð%ð "ô Œt�xŠx‹z‹?Ðøô œÐ&ô 	Ùð	ús   ÂA	C6 Ã6D
Ä	D
c                ó0   € V ^8„  d   QhR\         R\         /# )r9   rÜ   r;   r�   )r?   s   "r@   rA   rA   ÿ   s   € ÷ ñ œð ¤ñ rB   c           
      ó  €  R RRRRRRRR^/p\         P                  R8X  d   \        4       VR	&   \        P                  ! R
RV RR.3/ VBRR/B pVP
                  ^ 8X  d   VP                  P                  4       # R#   \         d     R# i ; i)Úcapture_outputTro   Úencodingúutf-8ÚerrorsÚreplaceÚtimeoutÚwin32ÚcreationflagsÚgitz-CÚbranchz--show-currentÚcheckFrÞ   )	ÚsysÚplatformr   Ú
subprocessÚrunÚ
returncodeÚstdouträ   Ú	Exception)rÜ   Ú
run_kwargsÚresults   &  r@   Ú_fs_git_branchr  ÿ   sž   € ð
ð '7¸¸fÀdÈJÐX_Ø&.°	¸9Àað&Iˆ
ä�<‰<˜7Ô"Ü*<Ó*>ˆJ�Ñ'Ü—’ ¨¨c°8Ð=MÐ NÑjÐR\ÑjÐdiÒjˆØ(.×(9Ñ(9¸QÔ(>ˆv�}‰}×"Ñ"Ó$ÐFÀBÐFøÜô Úðús   ‚A8A= Á;A= Á=BÂBc                ó:   € V ^8„  d   QhR\         \        ,          /# ©r9   Úprofile©r   r=   )r?   s   "r@   rA   rA     s   € ÷ 7ñ 7œ¤#�ñ 7rB   c                ó  € ^ RI Hp \        V 4      ;_uu_ 4        \        \	        4       P                  R4      ;'       g    / 4      p\        4       pRRR4       RRRRRR	R
R/P                  4        FA  w  rEXP                  V4      '       d   K  XP                  V4      '       g   K7  W5,          W$&   KC  	  T ;'       g    RP                  4       P                  4       ;'       g    RpV! VX4      #   + '       g   i     L¨; i)zFReturn the profile's SSH workspace adapter, or None for host-local FS.)Úget_ssh_workspace_fsrÛ   NÚssh_hostÚTERMINAL_SSH_HOSTÚssh_userÚTERMINAL_SSH_USERÚssh_portÚTERMINAL_SSH_PORTÚssh_keyÚTERMINAL_SSH_KEYÚcurrent)
Úhermes_cli.ssh_workspace_fsr	  r!   Údictr#   râ   r$   Úitemsrä   rD   )r  r	  rÛ   Úprofile_envÚkeyÚenv_nameÚprofile_keys   &      r@   Ú_fs_backendr    sÙ   € å@ä	˜×	 Õ	 Üœ›×)Ñ)¨*Ó5×;Ð;¸Ó<ˆÜ“jˆ÷ 
!ð 	Ð'ØÐ'ØÐ'ØÐ%ð	÷
 �eƒgò‰ˆð �|‰|˜C× Ô  [§_¡_°X×%>Ô%>Ø'Õ1ˆH‹Mñð ×'Ð'˜i×.Ñ.Ó0×6Ñ6Ó8×EÐE¸I€KÙ ¨XÓ6Ð6÷ 
!×	 ús   š7C1Ã1D	c                ó(   € V ^8„  d   QhR\         RR/# )r9   rš   r;   N)r   )r?   s   "r@   rA   rA      s   € ÷ ;ñ ;¤ð ;¨tñ ;rB   c                 ó  € ^ RI Hp \        W4      '       g   V hRRRRRRRR	R
RRRRR	/P                  V P                  R	4      pRRRRRRRRR
RRRRR/P                  V P                  \        V 4      ;'       g    R4      p\        W#R7      h)é    )ÚSshWorkspaceFsErrorÚEACCESr’   ÚECONNi÷  ÚEFBIGé�  ÚEINVALr¬   ÚEIOéö  ÚENOENTrª   ÚENOTREGr«   zSSH workspace is unavailableúFile too larger­   zSSH workspace request failedr¡   r¯   zFilesystem request failedr“   )r  r  Ú
isinstancerâ   Úcoder=   r   )rš   r  Ústatusr•   s   &   r@   Ú_raise_fs_backend_errorr,     sµ   € Ý?ä�c×/Ò/Øˆ	à�#Ø�Ø�Ø�#ØˆsØ�#Ø�3ð÷ 
�cˆ#�(‰(�CÓð ð 	Ð(ØÐ/ØÐ!Ø�.ØÐ-ØÐ"ØÐ3ð÷ 
�cˆ#�(‰(”C˜“H×;Ð;Ð ;Ó<ð ô  FÔ
:Ð:rB   c                ó:   € V ^8„  d   QhR\         \        ,          /# rÙ   )Úlistr   )r?   s   "r@   rA   rA   :  s   € ÷ ñ œD¤�Jñ rB   c                 óÐ   € \        4       p . pV R,          V R,          V R,          3 F#  p VP                  VP                  4       4       K%  	  V#   \        \        3 d     K=  i ; i)zÍDirectories GET /api/media may read: where the agent and attach pipeline
actually write media (images, screenshots, cache). Stops an authenticated
client reading image-suffixed files anywhere else on disk.ÚimagesÚscreenshotsÚcache)r"   Úappendræ   r™   rè   )ÚhomeÚoutÚroots      r@   Ú_media_serve_rootsr7  :  sg   € ô Ó€DØ€CØ˜• $¨Õ"6¸¸w½ÓGˆð	Ø�J‰J�t—|‘|“~Ö&ñ Hð
 €Jøô œÐ&ô 	Úð	ús   «AÁA%Á$A%c                ó0   € V ^8„  d   QhR\         R\        /# rJ   rr   )r?   s   "r@   rA   rA   H  s   € ÷ 2ñ 2œDð 2¤Sñ 2rB   c                óÊ   € \        V 4      ;_uu_ 4        V P                  4       pRRR4       \        P                  ! X4      P	                  R4      #   + '       g   i     L5; i)zaRead and encode a bounded file from a worker thread; 409 while a SQLite connection to it is live.NÚascii)r¿   rÉ   Úbase64Ú	b64encodeÚdecode)rK   r}   s   & r@   Ú_read_base64_filer>  H  sE   € ä	˜×	Õ	Ø�‰Ó ˆ÷ 
ô ×Ò˜DÓ!×(Ñ(¨Ó1Ð1÷ 
×	ús   ”AÁA"	z
/api/mediac                ó$   € V ^8„  d   QhR\         /# )r9   rK   r�   )r?   s   "r@   rA   rA   Q  s   € ÷ `ñ `œ#ñ `rB   c              ƒ  óø  a"  €  \        V 4      P                  4       P                  4       oSP                  P                  4       \        9  d   \        RRR7      h\        4       p\        ;QJ d    T3R lT 4       F  '       g   K   RM	  RM! T3R lT 4       4      '       g   \        R	R
R7      hSP                  4       '       g   \        RRR7      hSP                  4       P                  \        8”  d   \        RRR7      h\        P                   ! \"        S4      G Rj  x€L
 pRR\        SP                  P                  4       ,           RT 2/#   \        \        3 d    \        RRR7      hi ; i LS5i)zÐReturn a gateway-local image as a base64 data URL for remote clients
that can't read this machine's disk. Auth-gated; restricted to the image
allowlist, a size cap AND the resolved (symlink-safe) media roots.r¬   r­   r“   éŸ  úUnsupported media typec              3   ó\   <"  € T F!  pSV8H  ;'       g    VSP                   9   x € K#  	  R # 5irN   )Úparents)rP   r6  r·   s   & €r@   rR   Úget_media.<locals>.<genexpr>]  s)   øé € ÐJÁE¸Dˆv˜‰~×7Ð7 ¨¯©Ñ!7Ô7ÃEùs   ƒ,”,TFr’   zPath outside media rootsrª   r¡   r"  r(  NÚdata_urlúdata:ú;base64,)r   rå   ræ   r™   rè   r   ru   rD   Ú_MEDIA_CONTENT_TYPESr7  rT   Úis_filer±   Úst_sizeÚ_MEDIA_MAX_BYTESÚasyncioÚ	to_threadr>  )rK   ÚrootsÚencodedr·   s   &  @r@   Ú	get_mediarQ  P  s1  øé € ð
DÜ�d“×&Ñ&Ó(×0Ñ0Ó2ˆð ‡}�}×ÑÓÔ$8Ô8Ü¨Ð4LÔMÐMÜÓ €Eß‹3ÔJÁEÓJ�3�3Š3ÔJÁEÓJ×JÒJÜ¨Ð4NÔOÐOØ�>‰>×ÒÜ¨Ð4DÔEÐEØ‡{�{ƒ}×ÑÔ/Ô/Ü¨Ð4DÔEÐEä×%Ò%Ô&7¸Ó@×@€GØ˜%Ô 4°V·]±]×5HÑ5HÓ5JÕ KÐLÈHÐU\ÐT]Ð^Ð_Ð_øô ”\Ð"ô DÜ¨°NÔCÐCðDúñ Aùs;   ƒE:…'E ¬AE:ÂE:Â&"E:Ã	AE:Ä$E8Ä%1E:ÅE5Å5E:g      4@c                ó0   € V ^8„  d   QhR\         R\        /# )r9   Úhostr;   r<   )r?   s   "r@   rA   rA   t  s   € ÷ ñ ¤Cð ¬Dñ rB   c                 óÆ   a € S P                  4       P                  R 4      o \        ;QJ d#    V 3R l\         4       F  '       g   K   R# 	  R# ! V 3R l\         4       4      # )rà   c              3   ó¾   <"  € T FR  pSVP                  R 4      8H  ;'       g2    VP                  R 4      ;'       d    SP                  VR,          4      x € KT  	  R# 5i)z*.:é   NNN)ÚlstriprE   Úendswith)rP   ÚallowedrS  s   & €r@   rR   Ú,_media_proxy_host_allowed.<locals>.<genexpr>v  sT   øé € ð á1ˆGð 	�—‘˜tÓ$Ñ$×aÐa¨×);Ñ);¸DÓ)A×)`Ð)`ÀdÇmÁmÐT[Ð\^ÕT_ÓF`ÔaÛ1ùs   ƒA£A¼!ATF)rD   ÚrstriprT   Ú_MEDIA_PROXY_ALLOWED_HOSTS)rS  s   fr@   Ú_media_proxy_host_allowedr]  t  sT   ø€ Ø�:‰:‹<×Ñ˜sÓ#€Dß‹3ô å1ó�3Œ3ð Š3ð ˆ3ô å1óó ð rB   z/api/media/proxyc                ó0   € V ^8„  d   QhR\         R\        /# )r9   ÚurlÚrequest)r=   r   )r?   s   "r@   rA   rA   }  s   € ÷ &Añ &A¤#ð &A´ñ &ArB   c              ƒ  ó(  "  € \        V4        \        P                  P                  T ;'       g    RP	                  4       4      pTP                  R9  g   TP                  '       g   \        RRR7      h\        TP                  4      '       g   \        RRR7      hTP                  '       d7   \        TP                  4      P                  P                  4       \        9  di   \        TP                  4      P                  '       dD   \        TP                  4      P                  P                  4       \        9  d   \        RR	R7      h^ RIp TP!                  \"        R
R7      ;_uu_4       GRj  x€L
 pTP%                  T 4      G Rj  x€L
 pRRR4      GRj  x€L
  XP(                  ^È8w  d   \        RRTP(                   2R7      hTP*                  P%                  R4      ;'       g    RP-                  R4      ^ ,          P	                  4       P                  4       pT\        P/                  4       9  d   \        RR	R7      hTP0                  p\3        T4      \4        8”  d   \        RRR7      h\6        P8                  ! T4      P;                  R4      p	RRT RT	 2/#   \
         d   p\        RRR7      ThRp?ii ; i ELS EL= EL0  + GRj  x€L 
 '       g   i     ELH; i  \&         d   p\        RRT 2R7      hRp?ii ; i5i)zÈFetch a remote image URL the gateway can reach but the client cannot
(#74564), returning the same ``data_url`` shape as ``/api/media``. Only
allowlisted image CDNs; the bytes stay behind the size cap.rÞ   r¬   zA remote image URL is requiredr“   Nr’   zImage host not allowedrA  rB  T)rô   Úfollow_redirectsr%  zImage fetch failed: zImage fetch returned HTTP zcontent-typeÚ;r"  r(  r:  rF  rG  rH  )ÚhttpÚhttps)r%   ÚurllibÚparseÚurlparserä   Ú
ValueErrorr   ÚschemeÚhostnamer]  rK   r   ru   rD   rI  ÚhttpxÚAsyncClientÚ_MEDIA_PROXY_TIMEOUT_Srâ   r   r”   ÚheadersÚsplitÚvaluesÚcontentrŠ   rL  r;  r<  r=  )
r_  r`  Úparsedrš   rl  ÚclientÚresponseÚcontent_typer}   rP  s
   &&        r@   Úproxy_remote_mediarw  |  sq  é € ô
 �7Ôð_Ü—‘×&Ñ&¨¯	¨	¨r×'8Ñ'8Ó':Ó;ˆð ‡}�}Ð-Ô-°V·_·_°_Ü¨Ð4TÔUÐUÜ$ V§_¡_×5Ò5Ü¨Ð4LÔMÐMØ�;�;ˆ;œ$˜vŸ{™{Ó+×2Ñ2×8Ñ8Ó:ÔBVÔVô �—‘Ó×#×#Ð#¬¨V¯[©[Ó(9×(@Ñ(@×(FÑ(FÓ(HÔPdÔ(dÜ¨CÐ8PÔQÐQãðRØ×$Ñ$Ô-CÐVZÐ$×[×[Ô[Ð_eØ#ŸZ™Z¨›_×,ˆH÷ \×[ð
 ×Ñ˜sÔ"Ü¨Ð6PÐQY×QeÑQeÐPfÐ4gÔhÐhØ×$Ñ$×(Ñ(¨Ó8×>Ð>¸B×EÑEÀcÓJÈ1ÕM×SÑSÓU×[Ñ[Ó]€LØÔ/×6Ñ6Ó8Ô8Ü¨Ð4LÔMÐMØ×Ñ€DÜ
ˆ4ƒyÔ#Ô#Ü¨Ð4DÔEÐEä×Ò˜tÓ$×+Ñ+¨GÓ4€GØ˜% ˜~¨X°g°YÐ?Ð@Ð@øô? ô _Ü¨Ð4TÔUÐ[^Ð^ûð_úò  \Ú,÷ \×[×[Ô[ûäô RÜ¨Ð6JÈ3È%Ð4PÔQÐQûðRüsÎ   ‚L�7J( Á"LÁ)ALÂ0B"LÅ#K/ Å6K	Å7K/ Å:KÆKÆKÆK/ ÆKÆ K/ Æ$ALÇ1B7LÊ(KÊ3KËKËLË	K/ ËKËK/ ËK,	ËKË
K,	Ë$K,	Ë&K/ Ë*LË,K/ Ë/LË:L
Ì
LÌLc                óR   € V ^8„  d   QhR\         R\        \        \         3,          /# )r9   rF  r;   )r=   r¦   r~   )r?   s   "r@   rA   rA   ¦  s#   € ÷ ñ œsð ¤u¬U´C¨ZÕ'8ñ rB   c                 ó  € ^ RI Hp T ;'       g    RP                  4       pVP                  R4      '       d   RV9  d   \	        RRR7      hVP                  R^4      w  r4VR,          P                  R	^4      ^ ,          ;'       g    R
pRV9  d   \	        RRR7      h \        P                  ! VRR7      p\        T4      T8”  d   \	        RRR7      hYe3#   \        P                  \        3 d    \	        RRR7      hi ; i)r  ©Ú_MANAGED_FILE_MAX_BYTESrÞ   rG  Ú,r¬   z!Upload payload must be a data URLr“   :é   NNrc  rt   z;base64z%Upload payload must be base64 encodedT)Úvalidatez"Upload payload is not valid base64r"  úFile is too large)Úhermes_cli.web_serverr{  rä   rE   r   rp  r;  Ú	b64decodeÚbinasciiÚErrorri  rŠ   )rF  r{  ro   ÚheaderrP  Ú	mime_typer}   s   &      r@   Ú_decode_data_urlr†  ¦  sï   € Ý=Ø�NˆN˜×!Ñ!Ó#€DØ�?‰?˜7×#Ò# s°$¤Ü¨Ð4WÔXÐXØ—j‘j  aÓ(�O€FØ�r•
× Ñ   aÓ(¨Õ+×IÐIÐ/I€IØ˜ÔÜ¨Ð4[Ô\Ð\ðZÜ×Ò °$Ô7ˆô ˆ4ƒyÐ*Ô*Ü¨Ð4GÔHÐHØˆ?Ðøô	 �N‰NœJÐ'ô ZÜ¨Ð4XÔYÐYðZús   ÂC Ã)D c                ó>   € V ^8„  d   QhR\         R,          R\         /# )r9   ÚfilenameNr;   r�   )r?   s   "r@   rA   rA   À  s   € ÷ :ñ :¬C°$­Jð :¼3ñ :rB   c                 óð   € \        \        T ;'       g    R 4      P                  4       4      P                  p\        P
                  ! RRV4      pVP                  4       P                  R4      ;'       g    R# )rÞ   z[\x00-\x1f]+rz   rà   úpasted-image)r   r=   rä   r:   ÚreÚsub)rˆ  rë   s   & r@   Ú_sanitize_chat_image_filenamer�  À  sX   € Ü”S˜Ÿ˜ RÓ(×.Ñ.Ó0Ó1×6Ñ6€IÜ—’�¨¨YÓ7€IØ�?‰?Ó×"Ñ" 3Ó'×9Ð9¨>Ð9rB   c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r9   r}   r;   N)r~   r=   )r?   s   "r@   rA   rA   Æ  s   € ÷ ñ ¤ð ¬#°­*ñ rB   c                 óº   € V R ,          pVP                  R4      '       d   VR,          R8X  d   R# \         F   w  r#VP                  V4      '       g   K  Vu # 	  R# ):Né   Ns   RIFF:é   é   Ns   WEBPr*   N)rE   Ú_CHAT_IMAGE_MAGIC)r}   ÚheadÚsigÚexts   &   r@   Ú_chat_image_extensionr—  Æ  sM   € Ø��9€DØ‡��w×Ò D¨¥J°'Ô$9Ùß%‰ˆØ�?‰?˜3×ÔØŠJñ &ñ rB   c                ó\   € V ^8„  d   QhR\         R\        \        \        \        3,          /# )r9   Úpayloadr;   )r   r¦   r~   r=   )r?   s   "r@   rA   rA   Ð  s%   € ÷ 
 ñ 
 ¤ð 
 ¼5ÄÌÌSÀÕ;Qñ 
 rB   c                 óF  € \        V P                  4      w  rVP                  4       P                  R 4      '       g   \	        RRR7      h\        V4      \        8”  d   \        R,          p\	        RRV R2R7      h\        V4      pV\        9  d   \	        RRR7      hWV3# )	zimage/r¬   zUpload payload must be an imager“   r"  zImage is too large; cap is z MBzUnsupported image typei   )	r†  rF  rD   rE   r   rŠ   Ú_CHAT_IMAGE_UPLOAD_MAX_BYTESr—  Ú_CHAT_IMAGE_ALLOWED_EXTENSIONS)r™  r}   r…  Úmbr–  s   &    r@   Ú_decode_chat_image_uploadrž  Ð  s—   € Ü& w×'7Ñ'7Ó8�O€DØ�?‰?Ó×'Ñ'¨×1Ò1Ü¨Ð4UÔVÐVÜ
ˆ4ƒyÔ/Ô/Ü)¨kÕ:ˆÜ¨Ð6QÐRTÐQUÐUXÐ4YÔZÐZÜ
 Ó
%€CØ
Ô0Ô0Ü¨Ð4LÔMÐMØ˜CÐÐrB   z/api/chat/image-uploadc                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r9   r™  r  )r   r   r=   )r?   s   "r@   rA   rA   Þ  s   € ÷ ")ñ ")¤_ð ")¼xÌ½}ñ ")rB   c              ƒ  ó\   a a"  € V V3R lp\         P                  ! V4      G Rj  x€L
 #  L5i)aW  Persist a browser clipboard image where the embedded TUI can read it.

Browser clipboard bytes aren't visible to the server-side clipboard, so the
/chat page uploads them here and drives the TUI's ``/image <path>`` with
the returned gateway-visible path under ``HERMES_HOME/images/`` (the same
dir ``clipboard.paste`` / ``image.attach`` use).
c            
      óP  <€ \        S4      w  rp\        S	4      ;_uu_ 4        ^ RIHp V! 4       p\	        RR4      ;_uu_ 4        VP                  RRR7       RRR4       \        \        SP                  4      4      P                  ;'       g    Rp\        P                  ! RR	V4      P                  R
4      ;'       g    Rp\        P                  ! 4       P                  R4      pVRV R	\         P"                  ! ^4       R	V V 2,          p\	        RR4      ;_uu_ 4        VP%                  V 4       RRR4       RRR4       RRR\'        X4      RVP(                  R\+        V 4      RV/#   + '       g   i     EL; i  + '       g   i     LT; i  + '       g   i     L_; i)r  )Úget_image_cache_dirzImage directory is not writablez Could not create image directoryT©rD  Úexist_okNrŠ  z[^A-Za-z0-9_.-]+rz   z._-z%Y%m%d_%H%M%SÚ
dashboard_zCould not write imageÚokrK   r:   r~   r…  )rž  r!   Úgateway.platforms.baser£  r›   Úmkdirr   r�  rˆ  Ústemr‹  rŒ  rä   r   ÚnowÚstrftimeÚsecretsÚ	token_hexÚwrite_bytesr=   r:   rŠ   )
r}   r…  r–  r£  Úimg_dirrª  Útsr·   r™  r  s
           €€r@   Ú_runÚupload_chat_image.<locals>._runæ  sV  ø€ Ü8¸ÓAÑˆ˜Ü˜G×$Õ$ÝBÙ)Ó+ˆGÜÐ=Ð?a×bÕbØ—‘ d°T�Ô:÷ cô Ô5°g×6FÑ6FÓGÓH×MÑM×_Ð_ÐQ_ˆDÜ—6’6Ð-¨s°DÓ9×?Ñ?ÀÓF×XÐXÈ.ˆDÜ—’“×(Ñ(¨Ó9ˆBØ ¨B¨4¨q´×1BÒ1BÀ1Ó1EÐ0FÀaÈÀvÈcÈUÐSÕSˆFÜÐ=Ð?V×WÕWØ×"Ñ" 4Ô(÷ X÷ %ð �$Ø”C˜“KØ�F—K‘KØ”S˜“YØ˜ð
ð 	
÷ c×bÐbú÷ X×Wú÷ %×$úsH   £"FÁE.	Á6FÂ0FÃA#FÄ$F	Ä6FÅ.E?Å9	FÆFÆFÆF%	N)rM  rN  )r™  r  r²  s   ff r@   Úupload_chat_imager´  Ý  s$   ùé € ö
ô4 ×"Ò" 4Ó(×(Ð(Ñ(ùs   „!,¥*¦,z
/api/filesc                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r9   r`  rK   )r   r   r=   )r?   s   "r@   rA   rA     s"   € ÷ jñ j¤gð j´X¼cµ]ñ jrB   c              ƒ   óü  "  € \        W4      w  r#pVP                  4       '       g   \        R RR7      hVP                  4       '       g   \        RRR7      h\	        RR4      ;_uu_ 4        \
        P                  ! V4      ;_uu_ 4       p. pV FO  p\        VP                  4      p\        V4      '       d   K+  \        W(RR7      p	V	f   K>  VP                  V	4       KQ  	  R	R	R	4       R	R	R	4       XP                  R
 R7       VP                  p
R	pVP                  V8w  d    V
e   W:8w  d   \        VP                  4      pRVRVRV/\!        V4      C#   + '       g   i     L|; i  + '       g   i     L‡; i5i)rª   úPath not foundr“   r¬   zPath is not a directoryzDirectory is not readablezCould not read directoryT)Úskip_missingNc                 ó^   € V R ,          '       * \        V R,          4      P                  4       3# )Úis_directoryr:   )r=   rD   ©Úitems   &r@   Ú<lambda>Ú$list_managed_files.<locals>.<lambda>  s#   €  t¨NÕ';Ô#;¼SÀÀfÅÓ=N×=TÑ=TÓ=VÑ"WrB   ©r  rK   rÕ   Úentries)r   rÔ   r   rç   r›   r§   Úscandirr   rK   rV   r   r3  ÚsortÚlocked_rootrÕ   r=   r   )r`  rK   Úpolicyr·   Údisplay_pathÚscanrÁ  ÚentryÚ
entry_pathÚmetadatarÄ  rÕ   s   &&          r@   Úlist_managed_filesrË    s/  é € ä#8¸Ó#GÑ €F�LØ�=‰=�?Š?Ü¨Ð4DÔEÐEØ�=‰=�?Š?Ü¨Ð4MÔNÐNä	Ð/Ð1K×	LÕ	LÌbÏjÊjÐY_×N`ÔN`ÐdhØˆÛˆEÜ˜eŸj™jÓ)ˆJÜ! *×-Ò-ÙÜ*¨6ÈDÔQˆHØÔ#Ø—‘˜xÖ(ñ ÷ Oa×	Lð ‡L�LÑW€LÔXØ×$Ñ$€KØ€FØ‡}�}˜Ô KÒ$7¸6Ô;PÜ�V—]‘]Ó#ˆØ�L (¨F°I¸wÐiÔJ`ÐagÓJhÐiÐi÷ Oa×N`ú×	L×	LüsC   ‚AE<Á
!E<Á+E)Â
>E	ÃE	Ã"E)Ã*A,E<ÅE&Å!E)Å)E9	Å4E<c                ó|   € V ^8„  d   QhR\         R\        R\        \        \        \        \
        \        3,          /# )r9   r`  rK   r;   )r   r=   r¦   r   r   rÆ   )r?   s   "r@   rA   rA     s8   € ÷ Lñ L¤Gð L´3ð L¼5ÄÄdÌCÔQTÔVYÐAYÕ;Zñ LrB   c                ób  € ^ RI Hp \        WRR7      w  r4pVP                  4       '       g   \	        RRR7      hVP                  4       '       g   \	        RRR7      h\        V4      '       d   \	        R	R
R7      h\        P                  ! VP                  4      ^ ,          ;'       g    RpW4WRV3# )a  Resolve + guard a managed file for reading: existence, regular file,
sensitive-path denylist. Returns (policy, target, display_path, max_bytes,
mime_type). Callers own the live-SQLite 409 (held through the read for
/api/files/read, point-in-time for streamed responses).rz  T)Úfor_agent_readrª   r¡   r“   r¬   zPath is not a filer’   r°   rt   )
r€  r{  r   rÔ   r   rJ  rV   rw   rx   r:   )r`  rK   r{  rÅ  r·   rÆ  r…  s   &&     r@   Ú_managed_readable_filerÏ    s•   € õ
 >Ü#8¸ÐW[Ô#\Ñ €F�LØ�=‰=�?Š?Ü¨Ð4DÔEÐEØ�>‰>×ÒÜ¨Ð4HÔIÐIÜ˜&×!Ò!Ü¨Ð4^Ô_Ð_Ü×$Ò$ V§[¡[Ó1°!Õ4×RÐRÐ8R€IØ˜<À)ÐKÐKrB   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r9   r·   Ú	max_bytesr;   )r   rÆ   )r?   s   "r@   rA   rA   .  s!   € ÷ ñ œtð ´ð ¼ñ rB   c                 ó¨   €  V P                  4       P                  pY!8”  d   \        RRR7      hT#   \         d   p\        R RT 2R7      hRp?ii ; i)r–   zCould not stat file: r“   Nr"  r  )r±   rK  r™   r   )r·   rÑ  Úsizerš   s   &&  r@   Ú_managed_file_sizerÔ  .  s]   € ðSØ�{‰{‹}×$Ñ$ˆð ÔÜ¨Ð4GÔHÐHØ€Køô	 ô SÜ¨Ð6KÈCÈ5Ð4QÔRÐRûðSús   ‚1 ±A¼AÁAz/api/files/readc                ó0   € V ^8„  d   QhR\         R\        /# r¶  ©r   r=   )r?   s   "r@   rA   rA   9  s   € ÷ ñ ¤Wð ´Cñ rB   c              ƒ   ó6  "  € \        W4      w  r#rEp\        W54      p\        R R4      ;_uu_ 4        \        P                  ! \
        V4      G Rj  x€L
 pRRR4       RVP                  RVRVRVRRV R	X 2/\        V4      C#  L3  + '       g   i     L9; i5i)
r«   zCould not read fileNr:   rK   rÓ  r…  rF  rG  rH  )rÏ  rÔ  r›   rM  rN  r>  r:   r   )	r`  rK   rÅ  r·   rÆ  rÑ  r…  rÓ  rP  s	   &&       r@   Úread_managed_filerØ  8  s    é € ä9OÐPWÓ9^Ñ6€F�L¨YÜ˜fÓ0€DÜ	Ð*Ð,A×	BÕ	BÜ×)Ò)Ô*;¸VÓD×Dˆ÷ 
Cð 	�—‘Ø�Ø�Ø�YØ�e˜I˜; h¨w¨iÐ8ðô ! Ó
(ðð ñ E÷ 
C×	Büs.   ‚/B±BÁBÁBÁ/BÂBÂB	ÂBÚ
media_onlyFc          
      óT   € V ^8„  d   QhR\         R\        R\        R\        R\        /# )r9   r`  rK   Úcontent_disposition_typerÙ  r;   )r   r=   r>   r   )r?   s   "r@   rA   rA   H  s:   € ÷ ñ Üðä
ðô "ð	ô
 ðô ñrB   c             ƒ  ó`  "  € \        W4      w  rErgpV'       d1   VP                  P                  4       \        9  d   \	        RRR7      h\        WW4       \        P                  ! \        V4      G Rj  x€L
  \        \        V4      TVP                  TV'       d
   RR/R7      # RR7      #  L85i)z8Range-aware response after applying managed-file policy.rA  rB  r“   NzX-Content-Type-OptionsÚnosniff)rK   Ú
media_typerˆ  rÛ  ro  )rÏ  ru   rD   Ú_STREAMABLE_MEDIA_EXTENSIONSr   rÔ  rM  rN  rÃ   r   r=   r:   )	r`  rK   rÛ  rÙ  Ú_policyr·   Ú_display_pathrÑ  r…  s	   &&$$     r@   Ú_managed_file_responserâ  H  s¡   é € ô <RÐRYÓ;`Ñ8€G�]¨yß�f—m‘m×)Ñ)Ó+Ô3OÔOÜ¨Ð4LÔMÐMÜ�vÔ)Ü
×
Ò
Ô1°6Ó
:×:Ð:ÜÜ�‹[ØØ—‘Ø!9ß9CÐ)¨9Ð5ôð ð
 JNôð ñ ;ùs   ‚A1B.Á3B,Á49B.z/api/files/downloadc                ó0   € V ^8„  d   QhR\         R\        /# r¶  rÖ  )r?   s   "r@   rA   rA   _  s   € ÷ ñ ¬ð ¼ñ rB   c              ƒ  ó®   "  € V P                   P                  RR4      P                  4       pVR9   p\        T TV'       d   RMRVR7      G Rj  x€L
 #  L5i)a–  Stream a managed file as an attachment download.

``auth_middleware`` also accepts the session token as ``?token=`` here so a
shell/browser-opened download (no session header) still authenticates.
Chromium marks ``<audio>``/``<video>`` subresource requests via
``Sec-Fetch-Dest``; those are served inline for Desktop builds that still
use this route as their player source, attachment semantics otherwise.
zsec-fetch-destrÞ   ÚinlineÚ
attachment©rÛ  rÙ  N>   ÚaudioÚvideo)ro  râ   rD   râ  )r`  rK   Úfetch_destinationÚis_media_subresources   &&  r@   Údownload_managed_filerì  ^  s[   é € ð  Ÿ™×+Ñ+Ð,<¸bÓA×GÑGÓIÐØ,Ð0BÑBÐÜ'ØØß-A¡À|Ø'ô	÷ ð ñ ùs   ‚AAÁAÁAz/api/files/streamc                ó0   € V ^8„  d   QhR\         R\        /# r¶  rÖ  )r?   s   "r@   rA   rA   t  s   € ÷ kñ k¤wð k´cñ krB   c              ƒ  ó:   "  € \        WRRR7      G Rj  x€L
 #  L5i)uå   Stream managed audio/video inline with HTTP Range support â€” Electron's
media pipeline may reject an attachment response as an ``<audio>``/
``<video>`` source. Same auth, size cap, sensitive guard and MIME detection
as download.rå  Trç  N)râ  )r`  rK   s   &&r@   Ústream_managed_filerï  r  s   é € ô (¨ÐPXÐeiÔj×jÐjÑjùs   ‚”•c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r9   rK   r`  Ú	overwrite)r=   r   r>   )r?   s   "r@   rA   rA   |  s!   € ÷ (ñ (¤ð (¬gð (Ä$ñ (rB   c                 óò   € \        WR R7      w  r4pVP                  4       '       d$   VP                  4       '       d   \        RRR7      hVP                  4       '       d   V'       g   \        RRR7      hW4V3# )T©Ú	for_writer¾   z'A directory already exists at that pathr“   zFile already exists)r   rÔ   rç   r   )rK   r`  rñ  rÅ  r·   rÆ  s   &&&   r@   Ú_managed_write_targetrõ  |  s]   € Ü#8¸ÐRVÔ#WÑ €F�LØ‡}�}‡‚˜6Ÿ=™=Ÿ?š?Ü¨Ð4]Ô^Ð^Ø‡}�}‡‚ŸyÜ¨Ð4IÔJÐJØ˜<Ð'Ð'rB   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r9   r·   rÆ  r;   )r   r=   r  )r?   s   "r@   rA   rA   …  s!   € ÷ ñ ¬$ð ¼cð Ädñ rB   c                 ó:   € R RR\        W4      RV/\        V 4      C# )r§  TrÈ  rK   )r   r   )rÅ  r·   rÆ  s   &&&r@   Ú_managed_write_resultrø  …  s0   € àˆdØÔ$ VÓ4Ø�ðô ! Ó
(ð	ð rB   z/api/files/uploadc                ó0   € V ^8„  d   QhR\         R\        /# ©r9   r™  r`  )r    r   )r?   s   "r@   rA   rA   �  s   € ÷ ?ñ ?Ô'8ð ?Ä7ñ ?rB   c              ƒ   óR  "  € \        V P                  WP                  4      w  r#p\        V P                  4      w  rV\        R R4      ;_uu_ 4        VP                  P                  RRR7       VP                  V4       RRR4       \        W#V4      #   + '       g   i     L; i5i)úFile is not writableúCould not write fileTr¤  N)
rõ  rK   rñ  r†  rF  r›   rÕ   r©  r¯  rø  )r™  r`  rÅ  r·   rÆ  r}   Ú
_mime_types   &&     r@   Úupload_managed_filerÿ  Ž  s…   é € ä#8¸¿¹Àw×PaÑPaÓ#bÑ €F�LÜ'¨×(8Ñ(8Ó9Ñ€DÜ	Ð*Ð,B×	CÕ	CØ�‰×Ñ D°4ÐÔ8Ø×Ñ˜4Ô ÷ 
Dô ! °Ó>Ð>÷ 
D×	Cüs   ‚AB'Á/BÂ B'ÂB$	ÂB'c                ó`   € V ^8„  d   QhR\         R\        R\        R\        R\        R\        /# )r9   Úfiler·   Ú	too_largeÚnot_writableÚwrite_failedr;   )r   r   r=   rÆ   )r?   s   "r@   rA   rA   ˜  sD   € ÷ )ñ )Ü
ð)äð)ô ð	)ô
 ð)ô ð)ô 	ñ)rB   c             ƒ  óh  "  € ^ RI HpHp \        P                  ! RVP
                   R2R\        VP                  4      R7      w  rx\        V4      p	^ p
Rp \        P                  ! VR4      ;_uu_ 4       p V P                  V4      G Rj  x€L
 pV'       g   M8V
\        V4      ,          p
W¥8”  d   \        R	VR
7      hVP                  V4       K[  RRR4       \        P                  ! W‘4       Rp T'       g   T	P%                  RR7       T P'                  4       G Rj  x€L
  T
#  Lš  + '       g   i     L_; i  \          d    \        RTR
7      h\"         d   p\        RT RT 2R
7      hRp?ii ; i LW  T'       g   T	P%                  RR7       T P'                  4       G Rj  x€L 
  i ; i5i)u›  Stream a multipart upload to ``target`` in chunks; returns bytes written.

Writes a sibling temp file first so a partial/aborted upload never clobbers
an existing file, enforces ``_MANAGED_FILE_MAX_BYTES`` as it goes (413
``too_large``), then atomically renames into place. The temp file is
removed on EVERY non-success exit â€” including asyncio.CancelledError when a
browser aborts a large upload mid-stream.
)r{  Ú_UPLOAD_CHUNK_BYTESrà   z.upload)Úprefixru   ÚdirFÚwbTNr"  r“   r’   r–   r—   ©Ú
missing_ok)r€  r{  r  ÚtempfileÚmkstempr:   r=   rÕ   r   r§   ÚfdopenrË   rŠ   r   Úwriteró   r˜   r™   ÚunlinkÚclose)r  r·   r  r  r  r{  r  Útmp_fdÚtmp_nameÚtmp_pathÚtotalÚrenamedr5  Úchunkrš   s   &&$$$          r@   Ústream_upload_to_pathr  ˜  se  é € ÷  SÜ×'Ò'°°6·;±;°-¸qÐ/AÈ)ÔY\Ð]c×]jÑ]jÓYkÔlÑ€FÜ�H‹~€HØ€EØ€GðÜ�YŠY�v˜t×$Ô$¨ØØ"Ÿi™iÐ(;Ó<×<�ßØØœ˜U›Õ#�ØÔ2Ü'°CÀ	ÔJÐJØ—	‘	˜%Ö ÷ %ô 	�
Š
�8Ô$Ø‰÷ Ø�O‰O tˆOÔ,Ø�j‰j‹l×ÐØ€Lñ# =÷ %×$ûô ô BÜ¨°LÔAÐAÜô NÜ¨°|°nÀBÀsÀeÐ4LÔMÐMûðNúñ
 	ø÷ Ø�O‰O tˆOÔ,Ø�j‰j‹l×Òüs�   ‚AF2ÁD< Á6D)ÂD'ÂD)Â9D)Ã D< Ã3F2Ã;%F2Ä E8Ä!F2Ä'D)Ä)D9	Ä4D< Ä< E5ÅE5ÅE0Å0E5Å5E: Å8F2Å:.F/Æ(F+Æ)F/Æ/F2z/api/files/upload-stream.Tc                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r9   r`  r  rK   rñ  )r   r   r=   r>   )r?   s   "r@   rA   rA   Å  s0   € ÷ ?ñ ?Üð?ä
ð?ô ð?ô ñ	?rB   c              ƒ  ó  "  € \        W V4      w  rEp\        RR4      ;_uu_ 4        VP                  P                  RRR7       RRR4       \	        WRRRR7      G Rj  x€L
  \        WEV4      #   + '       g   i     L3; i L#5i)	z™Chunked multipart upload: constant memory and no base64 inflation, unlike
the JSON data-URL endpoint that trips proxy body-size limits on large archives.rü  z!Could not create parent directoryTr¤  Nr  rý  )r  r  r  )rõ  r›   rÕ   r©  r  rø  )r`  r  rK   rñ  rÅ  r·   rÆ  s   &&&&   r@   Úupload_managed_file_streamr  Ä  s€   é € ô $9¸È	Ó#RÑ €F�LÜ	Ð*Ð,O×	PÕ	PØ�‰×Ñ D°4ÐÔ8÷ 
Qä
ØØ%Ø+Ø+ô	÷ ð ô ! °Ó>Ð>÷ 
Q×	Púñùs(   ‚$B¦A/ÁBÁBÁBÁ/A?	Á:	Bz/api/files/mkdirc                ó0   € V ^8„  d   QhR\         R\        /# rú  )r   r   )r?   s   "r@   rA   rA   Ú  s   € ÷ ?ñ ?Ô,Bð ?ÌWñ ?rB   c              ƒ   óP  "  € \        V P                  VR R7      w  r#pVP                  4       '       d$   VP                  4       '       g   \	        RRR7      h\        RR4      ;_uu_ 4        VP                  R R R7       RRR4       \        W#V4      #   + '       g   i     L; i5i)	Tró  r¾   z"A file already exists at that pathr“   zDirectory is not writablezCould not create directoryr¤  N)r   rK   rÔ   rç   r   r›   r©  rø  )r™  r`  rÅ  r·   rÆ  s   &&   r@   Úcreate_managed_directoryr  Ù  s{   é € ä#8¸¿¹ÀwÐZ^Ô#_Ñ €F�LØ‡}�}‡‚˜vŸ}™}ŸšÜ¨Ð4XÔYÐYÜ	Ð/Ð1M×	NÕ	NØ�‰˜T¨DˆÔ1÷ 
Oä  °Ó>Ð>÷ 
O×	Nüs$   ‚AB&Á
!B&Á+BÁ?B&ÂB#	ÂB&c                ó0   € V ^8„  d   QhR\         R\        /# rú  )r   r   )r?   s   "r@   rA   rA   ä  s   € ÷ Pñ PÔ'8ð PÄ7ñ PrB   c              ƒ   ó˜  "  € \        V P                  V4      w  r#pVP                  e   W2P                  8X  d   \        RRR7      hVP                  V8X  d   \        RRR7      hVP                  4       '       g   \        RRR7      h VP                  4       '       d;   V P                  '       d   \        P                  ! V4       M"VP                  4        MVP                  4         R
RRV/\        V4      C#   \         dB   pTP                  4       '       d   T P                  '       g   RMRp\        TR	T 2R7      hR p?ii ; i5i)Nr¬   z$Cannot delete the managed files rootr“   z!Cannot delete the filesystem rootrª   r¸  r¾   r–   zCould not delete path: r§  TrK   )r   rK   rÄ  r   rÕ   rÔ   rç   Ú	recursiveÚshutilÚrmtreeÚrmdirr  r™   r   )r™  r`  rÅ  r·   rÆ  rš   r”   s   &&     r@   Údelete_managed_filer%  ã  s  é € ä#8¸¿¹ÀwÓ#OÑ €F�LØ×ÑÒ%¨&×4FÑ4FÔ*FÜ¨Ð4ZÔ[Ð[Ø‡}�}˜ÔÜ¨Ð4WÔXÐXØ�=‰=�?Š?Ü¨Ð4DÔEÐEð
]Ø�=‰=�?Š?Ø× × Ð Ü—’˜fÕ%à—‘•à�M‰M�Oð �$˜ ÐOÔ0FÀvÓ0NÐOÐOøô ô ]Ø#Ÿ]™]Ÿ_š_°W×5F×5FÐ5F‘cÈCˆÜ¨Ð>UÐVYÐUZÐ<[Ô\Ð\ûð]üsZ   ‚A8E
Á;E
Â	C; ÂC; Â1C; ÃE
ÃC; ÃE
ÃC; Ã)E
Ã;EÄ'EÄ.EÅEÅE
r&  ÚENOTDIRr  z/api/fs/listc                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# ©r9   rK   r`  r  ©r=   r   r   )r?   s   "r@   rA   rA     s*   € ÷ Xñ Xœð X¤gð X¼Ä½ñ XrB   c              ƒ   óÎ  "  € \         P                  ! \        V4      G R j  x€L
 pVe0    \         P                  ! VP                  V \        4      G R j  x€L
 # \        V \        V4      R7      p\        WQ4        . p\        P                  ! V4      ;_uu_ 4       pV Fˆ  pVP                  \        9   g%   \        \        VP                  4      4      '       d   K>  VP!                  RVP                  R\#        WXP                  ,          4      RVP%                  RR7      /4       KŠ  	  R R R 4       VP'                  R R7       R	V/#  EL( L÷  \
         d   p\        T4        R p?ELR p?ii ; i  + '       g   i     LP; i  \(         dS   p\*         F#  w  rš\-        YI4      '       g   K  R	. R
T
/u u R p?# 	  R	. R
\/        TRR 4      ;'       g    R/u R p?# R p?ii ; i5i)Nr    r:   rK   ÚisDirectoryF)Úfollow_symlinksc                 ó\   € V R ,          '       * V R,          P                  4       V R,          3# )r+  r:   )rD   r¼  s   &r@   r¾  Úfs_list.<locals>.<lambda>  s'   € ¨4°Õ+>Ô'>ÀÀVÅ×@RÑ@RÓ@TÐVZÐ[aÕVbÑ&crB   rÀ  rÁ  ÚerrorÚstrerrorz
read-error)rM  rN  r  Úlist_dirÚ_FS_READDIR_HIDDENr   r,  r   Ú_fs_profile_homer   r§   rÂ  r:   rV   r   rK   r3  r=   rç   rÃ  r™   Ú_FS_LIST_ERRNOr)  Úgetattr)rK   r`  r  Úbackendrš   r·   rÁ  rÇ  rÈ  Úexc_typer*  s   &&&        r@   Úfs_listr8    s�  é € ä×%Ò%¤k°7Ó;×;€GØÒð	)Ü ×*Ò*¨7×+;Ñ+;¸TÔCUÓV×VÐVô ˜DÔ/?ÀÓ/HÔI€FÜ˜&Ô*ðXØˆÜ�ZŠZ˜×Ô 4Û�Ø—:‘:Ô!3Ô3Ô7IÌ$ÈuÏzÉzÓJZ×7[Ò7[ÙØ—‘Ø˜EŸJ™JØœC ¯©Õ 3Ó4Ø! 5§<¡<À <Ó#Fð ö ñ ÷  ð 	�‰ÑcˆÔdØ˜7Ð#Ð#ò) <ñ WøÜô 	)Ü# C×(Ò(ûð	)ú÷  ×ûô ô Xß,‰NˆHÜ˜#×(Ô(Ø! 2 w°Ð5×5ñ -ð ˜2˜w¬°°ZÀÓ(F×(VÐ(VÈ,ÐWÕWûð	Xüs±   ‚G%¡E	¢G%«)E ÁEÁE Á"G%Á; F ÂBE2Ä*F ÅG%ÅE ÅE/ÅE*Å$G%Å*E/Å/G%Å2F	Å=F ÆG"ÆGÆ.GÆ5G"Æ6G%Æ;GÇGÇG"ÇG%ÇG"Ç"G%z/api/fs/read-textc                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# r(  r)  )r?   s   "r@   rA   rA   !  s%   € ÷ 'ñ 'œSð '¬7ð 'ÄHÌSÅMñ 'rB   c              ƒ   ó>  "  € \         P                  ! \        V4      G R j  x€L
 pVe±    \         P                  ! VP                  V \        \
        R7      G R j  x€L
 w  rEp\        X4      pR\        XR,          4      RXR\        P                  VP                  P                  4       R4      R\        V4      RVRVP                  R	R
R7      RV\
        8„  /# \!        V4      p	\#        W	R7      p\%        Wa4       \'        Wi4      w  rjV
P(                  \        8”  d   \+        RRR7      h\         P                  ! \,        V\/        V
P(                  \
        4      4      G R j  x€L
 pR\        VR,          4      RV
P(                  R\        P                  VP                  P                  4       R4      R\        V4      R\1        V4      RVP                  R	R
R7      RV
P(                  \
        8„  /#  ELÐ ELš  \         d   p\        T4        R p?EL±R p?ii ; i L¸5i)N)rÑ  Ú
read_limitÚbinary:Ni   NÚbyteSizeÚlanguagero   ÚmimeTyperK   rñ   ró   )rò   Ú	truncatedr    r"  r(  r“   )rM  rN  r  rÉ   Ú_FS_TEXT_SOURCE_MAX_BYTESÚ_FS_TEXT_PREVIEW_MAX_BYTESr   r,  r   rŒ   Ú_FS_PREVIEW_LANGUAGE_BY_EXTrâ   ru   rD   r{   r=  r3  r   r   r¹   rK  r   rÍ   Úminr=   )rK   r`  r  r6  r}   rÓ  r·   rš   Útarget_pathrž   r¸   s   &&&        r@   Úfs_read_textrF     sÚ  é € ä×%Ò%¤k°7Ó;×;€GØÒð	)Ü'.×'8Ò'8Ø×"Ñ"ØÜ3Ü5ô	(÷ "ÑˆD˜ô ˜6“lˆàÔ& t¨E¥{Ó3Ø˜ØÔ3×7Ñ7¸×8JÑ8J×8PÑ8PÓ8RÐTZÓ[Øœ kÓ2Ø�FØ�D—K‘K °	�KÓ:Ø˜Ô :Ñ:ð
ð 	
ô $ GÓ,€LÜ˜DÔ<€FÜ˜&Ô*Ü! &Ó7�J€FØ	‡z�zÔ-Ô-Ü¨Ð4DÔEÐEÜ×"Ò"Ü˜¤ B§J¡JÔ0JÓ Kó÷ €Dð 	Ô" 4¨¥;Ó/Ø�B—J‘JØÔ/×3Ñ3°F·M±M×4GÑ4GÓ4IÈ6ÓRØ”M &Ó)Ø”�F“Ø�—‘˜G¨I�Ó6Ø�R—Z‘ZÔ"<Ñ<ðð ò= <ò"øô ô 	)Ü# C×(Ò(ûð	)úñ$ùsX   ‚H¡G1¢H«/G7 ÁG4ÁG7 Á"D HÅ"HÅ#BHÇ4G7 Ç7HÈHÈHÈHÈHz/api/fs/write-textc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r   )r   r   r=   )r?   s   "r@   rA   rA   L  s"   € ÷ 5Tñ 5T¤ð 5T´xÄµ}ñ 5TrB   c           
   ƒ  óÄ  "  € V P                   ;'       g    Rp\        P                  ! \        V4      G Rj  x€L
 pVeF    \        P                  ! VP                  V P
                  V\        R7      G Rj  x€L
 w  rERRRXRX/# \        V P
                  RR	7      p\        VP                  R
4      4      \        8”  d   \        RRR7      h VP                  4       pTe4   \        P$                  ! TP&                  4      '       d   \        RRR7      hTe4   \        P(                  ! TP&                  4      '       g   \        RRR7      hTP*                  P-                  4       '       g   \        RRR7      hTP/                  RTP0                   R\2        P4                  ! 4        24      p TP	                  TR
R7       \2        P6                  ! Y„4       RRR\#        T4      R\        TP                  R
4      4      /#  ELÈ ELŒ  \         d   p\        T4        Rp?EL¤Rp?ii ; i  \         d    Rp EL\\         d    \        RRR7      h\          d&   p\        R\#        T4      ;'       g    RR7      hRp?ii ; i  \         d!    TP9                  RR7       \        RRR7      h\          d(   pTP9                  RR7       \        RRT 2R7      hRp?ii ; i5i)a§  Overwrite (or create) a UTF-8 text file for the in-app spot editor.

Mirrors the Electron ``hermes:fs:writeText`` hardening: path validated by
``_fs_path``, the parent must already exist (never build trees), only
regular files may be replaced, payload size-capped, staged to a sibling
temp file and ``os.replace``-d so a crash can't truncate the original.
Stale-on-disk detection is the client's job (re-read before save).
rÞ   N©rÑ  r§  TrK   r=  F)Údecode_fallbackrñ   r"  zContent too larger“   r’   rü  r¬   r­   r®   z!Only regular files can be writtenzParent directory does not existrà   z.hermes-tmp-)rð   r
  r–   zCould not write file: )rr  rM  rN  r  Ú
write_textrK   Ú_FS_TEXT_WRITE_MAX_BYTESr   r,  r   rŠ   Úencoder   r±   r²   r˜   r™   r=   r´   rµ   r¶   rÕ   rç   Ú	with_namer:   r§   Úgetpidró   r  )	r™  r  ro   r6  r·   Ú	byte_sizerš   r¸   Útmps	   &&       r@   Úfs_write_textrR  K  sp  é € ð �?‰?× Ð ˜b€DÜ×%Ò%¤k°7Ó;×;€GØÒð	)Ü&-×&7Ò&7Ø×"Ñ"Ø—‘ØÜ2ô	'÷ !ÑˆFð �d˜F F¨J¸	ÐBÐBä�g—l‘l°EÔ:€FÜ
ˆ4�;‰;�wÓÓ Ô#;Ô;Ü¨Ð4GÔHÐHðPØ'-§{¡{£}ˆð 
‚~œ$Ÿ,š, r§z¡z×2Ò2Ü¨Ð4PÔQÐQØ	‚~œdŸlšl¨2¯:©:×6Ò6Ü¨Ð4WÔXÐXØ�=‰=×Ñ×!Ò!Ü¨Ð4UÔVÐVà
×
Ñ
˜Q˜vŸ{™{˜m¨<¼¿	º	»°}ÐEÓ
F€CðTØ�‰�t gˆÔ.Ü
�
Š
�3Ôð �$˜¤ F£¨Z¼¸T¿[¹[ÈÓ=QÓ9RÐSÐSòW <ò!øô ô 	)Ü# C×(Ò(ûð	)ûô ô Ø‹Üô LÜ¨Ð4JÔKÐKÜô PÜ¨´C¸³H×4NÐ4NÀÔOÐOûðPûô ô LØ�
‰
˜dˆ
Ô#Ü¨Ð4JÔKÐKÜô TØ�
‰
˜dˆ
Ô#Ü¨Ð6LÈSÈEÐ4RÔSÐSûðTüsÅ   ‚5K ·G?¸K Á5H Á6HÁ7H Á=AK ÃH) Ã)K Ä6K Ä>,K Å+AK Æ-)J Ç*K ÈH ÈH&ÈH!ÈK È!H&È&K È)I?È6K È9I?ÉI?ÉI?É I:É:I?É?K Ê2KÊ5KÊ6"KËKËK c                ót   € V ^8„  d   QhR\         R\        \         ,          R\        \         ,          R\        /# )r9   rK   r  Ú
session_idr;   )r=   r   r   )r?   s   "r@   rA   rA   „  s2   € ÷ ;ñ ;¤#ð ;´¼µð ;Ì8ÔTWÍ=ð ;Ô]añ ;rB   c              ƒ   ó  "  € \        V4      pVe`   ^ RIHp VP                  4       '       g   \	        RRR7      hV! W!4      G R j  x€L
 p\        YP                  R4      ;'       g    RVR7      # \        WR7      #  L65i)	N)Úget_session_detailrª   zSession not foundr“   rÜ   rÞ   )rÜ   rž   r    )r3  Úhermes_cli.web_routers.sessionsrV  rä   r   r   râ   )rK   r  rT  rž   rV  Úsessions   &&&   r@   Ú_fs_download_pathrY  „  sq   é € ä# GÓ,€LØÒÝFà×Ñ×!Ò!Ü¨CÐ8KÔLÐLÙ*¨:Ó?×?ˆä˜d¯©°EÓ(:×(@Ð(@¸bÈ|Ô\Ð\Ü˜$Ô:Ð:ñ @ùs   ‚+A?®A?ÁA=Á A?Á(A?c                ó\   € V ^8„  d   QhR\         \        ,          R\         \        ,          /# )r9   r  r;   )r   r=   r   )r?   s   "r@   rA   rA   ’  s"   € ÷ 	*ñ 	*œh¤s�mð 	*´¼µñ 	*rB   c                óX   € ^ RI Hp ^ RIHp V! V 4      '       d   R# V! V 4      ^,          # )z«HERMES_HOME of a requested profile (404/400 on an unknown one), None for the request's
own profile (omitted, ``""`` or ``current``, as ``_is_current_profile`` reads them).)Ú_cron_profile_home)Ú_is_current_profileN)Úhermes_cli.web_server_cronr\  Úhermes_cli.web_server_profilesr]  )r  r\  r]  s   &  r@   r3  r3  ’  s(   € õ >ÝBá˜7×#Ò#Ùá˜gÓ& qÕ)Ð)rB   z/api/fs/read-data-urlc          	      ót   € V ^8„  d   QhR\         R\        R\        \         ,          R\        \         ,          /# ©r9   rK   r`  r  rT  r)  )r?   s   "r@   rA   rA   Ÿ  s;   € ÷ Iñ IÜ
ðIÜðIÜ*2´3­-ðIÜLTÔUXÍMñIrB   c              ƒ   ó²  a"  € ^ RI Hp \        P                  ! \        V4      G Rj  x€L
 pVep    \        P                  ! VP
                  WR7      G Rj  x€L
 w  rgo\        P                  ! X4      P                  R4      p	RR\        \        S4      4       RV	 2/# \        WV4      G Rj  x€L
 o\        SV4       \        S\!        V4      4      w  op
V
P"                  V8”  d   \%        RR	R
7      h\        P                  ! V3R l4      G Rj  x€L
 p	RR\        S4       RV	 2/#  EL LÖ  \         d   p\        T4        Rp?LìRp?ii ; i L£ LA5i)r  )Ú_FS_DATA_URL_MAX_BYTESNrI  r:  ÚdataUrlrG  rH  r"  r(  r“   c                  ó`   <€ \         P                  ! \        S 4      4      P                  R 4      # )r:  )r;  r<  rÍ   r=  rÂ   s   €r@   r¾  Ú"fs_read_data_url.<locals>.<lambda>³  s    ø€ ”× Ò ¤°Ó!7Ó8×?Ñ?ÀÔHrB   )r€  rc  rM  rN  r  rÉ   r   r,  r;  r<  r=  r{   r   rY  r   r¹   r3  rK  r   )rK   r`  r  rT  rc  r6  r}   Ú_sizerš   rP  r¸   r·   s   &&&&       @r@   Úfs_read_data_urlrh  ž  sC  øé € õ =Ü×%Ò%¤k°7Ó;×;€GØÒð	)Ü(/×(9Ò(9Ø×"Ñ" Dô)÷ #ÑˆD˜ô
 ×"Ò" 4Ó(×/Ñ/°Ó8ˆØ˜U¤=´°f³Ó#>Ð"?¸xÈÀyÐQÐRÐRÜ$ T°JÓ?×?€FÜ˜& 'Ô*Ü! &Ô*:¸7Ó*CÓD�J€FˆBØ	‡z�zÐ*Ô*Ü¨Ð4DÔEÐEÜ×%Ò%ÜHó÷ €Gð ˜œ}¨VÓ4Ð5°X¸g¸YÐGÐHÐHò% <ñ#øô ô 	)Ü# C×(Ñ(ûð	)úñ @ñ
ùsj   ƒ%E¨D+©E²%D0 ÁD.ÁD0 ÁAEÂ/EÂ0A#EÄEÄEÄ.D0 Ä0EÄ;EÅEÅEÅEÅEz/api/fs/downloadc          	      ót   € V ^8„  d   QhR\         R\        R\        \         ,          R\        \         ,          /# ra  r)  )r?   s   "r@   rA   rA   ¹  s6   € ÷ ñ Ü
ðÜðÜ19¼#µðÜS[Ô\_ÕS`ñrB   c              ƒ   ó  "  € \         P                  ! \        V4      G R j  x€L
 pVeª    \         P                  ! VP                  V 4      G R j  x€L
 w  rV\        X4      p\        V4      '       d   \        RRR7      h\        P                  P                  VP                  4      p	\        VP                  V4      \        V4      RRV	 2/R7      # \!        WV4      G R j  x€L
 p\#        WQ4       \%        V\'        V4      4      w  rZ\         P                  ! \(        V4      G R j  x€L
  \+        \-        V4      \        V4      VP                  RR7      #  EL6 EL  \         d   p\        T4        R p?EL#R p?ii ; i Lž L[5i)	Nr’   r°   r“   zContent-Dispositionzattachment; filename*=UTF-8'')rÞ  ro  ræ  )rK   rÞ  rˆ  rÛ  )rM  rN  r  Úinspect_filer   r,  r   rV   r   rf  rg  Úquoter:   r   Ústream_filer{   rY  r   r¹   r3  rÃ   r   r=   )rK   r`  r  rT  r6  r·   rg  rš   rE  rˆ  Ú_sts   &&&&       r@   Úfs_downloadro  ¸  sP  é € ô ×%Ò%¤k°7Ó;×;€GØÒð	)Ü")×"3Ò"3°G×4HÑ4HÈ$Ó"O×O‰MˆFô ˜6“lˆÜ˜k×*Ò*Ü¨CÐ8bÔcÐcÜ—<‘<×%Ñ% k×&6Ñ&6Ó7ˆÜ Ø×Ñ Ó'Ü$ [Ó1Ø*Ð.KÈHÈ:Ð,VÐWô
ð 	
ô
 % T°JÓ?×?€FÜ˜&Ô*Ü" 6Ô+;¸GÓ+DÓE�K€FÜ
×
Ò
Ô1°6Ó
:×:Ð:ÜÜ�‹[Ü  Ó(Ø—‘Ø!-ô	ð ò' <ò PøÜô 	)Ü# C×(Ò(ûð	)úñ @ñ ;ùsj   ‚F¡E¢F«$E ÁEÁE ÁBFÃ"FÃ#AFÄ'FÄ(0FÅE ÅE>Å(E9Å3FÅ9E>Å>FÆFz/api/fs/git-rootc                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r9   rK   r  )r=   r   )r?   s   "r@   rA   rA   Ø  s   € ÷ .ñ .œCð .¬(´3­-ñ .rB   c              ƒ   óÞ  "  € \         P                  ! \        V4      G R j  x€L
 pVe-    R\         P                  ! VP                  V 4      G R j  x€L
 /# \        V 4      p VP                  4       p\        P                  ! VP                  4      '       d   TMVP                  pR\        V4      /#  L‘ Ld  \         d   p\        T4        R p?L|R p?ii ; i  \         d    Tp LCi ; i5i)Nr6  )rM  rN  r  Úgit_rootr   r,  r   r±   r´   rµ   rÕ   r™   r×   )rK   r  r6  rš   r·   r¸   rÏ   s   &&     r@   Úfs_git_rootrs  ×  sË   é € ä×%Ò%¤k°7Ó;×;€GØÒð	)Ø¤'×"3Ò"3°G×4DÑ4DÀdÓ"K×KÐLÐLô �d‹^€FðØ�[‰[‹]ˆÜŸ,š, r§z¡z×2Ò2‘¸¿¹ˆð Ô% eÓ,Ð-Ð-ñ <ñ LøÜô 	)Ü# C×(Ñ(ûð	)ûô ô ØŠðüso   ‚C-¡B3¢C-«%B7 ÁB5ÁB7 ÁC-Á"AC Â&C-Â5B7 Â7CÃCÃC-ÃCÃC-ÃC*Ã'C-Ã)C*Ã*C-z/api/fs/default-cwdc                ó:   € V ^8„  d   QhR\         \        ,          /# r  r  )r?   s   "r@   rA   rA   é  s   € ÷ 
7ñ 
7¤(¬3¥-ñ 
7rB   c              ƒ   óP  "  € \         P                  ! \        V 4      G R j  x€L
 pVe=   VP                  p \         P                  ! VP                  V4      G R j  x€L
 pRVRX/# \        4       pRVR\        V4      /#  L] L%  \
         d   p\        T4        R p?L>R p?ii ; i5i)NrÜ   rø   )	rM  rN  r  rÜ   Ú
git_branchr   r,  rì   r  )r  r6  rÜ   rø   rš   s   &    r@   Úfs_default_cwdrw  è  s›   é € ä×%Ò%¤k°7Ó;×;€GØÒØ�k‰kˆð	)Ü"×,Ò,¨W×-?Ñ-?ÀÓE×EˆFð �s˜H fÐ-Ð-Ü
Ó
€CØ�3˜¤.°Ó"5Ð6Ð6ñ <ñ FøÜô 	)Ü# C×(Ñ(ûð	)üsJ   ‚B&¡A?¢B&·$B ÁBÁB Á  B&ÂB ÂB#ÂBÂB&ÂB#Â#B&c                ó|   € V ^8„  d   Qh/ ^ \         9   d(   \        \        \        \        3,          R3,          ;R&   # )r9   .r“  )Ú__conditional_annotations__r¦   r~   r=   )r?   s   "r@   rA   rA      s7   € ÷ ñ ÷rò ”5œœu¤c˜zÕ*¨CÐ/Õ0ñ òsrB   i  �>   r,   r.   r/   r0   r1   r2   r3   r5   r-   r4   r6   >   ÚdistÚvenvÚbuildr·   Ú__pycache__Únode_modulesú.hgrÒ   ú.svnú.nextú.venvú.cacheú.turbo>   Úcredentialsú	auth.jsonú	auth.lockúconfig.yamlúbws_cache.jsonú.git-credentialsúgoogle_oauth.jsonúgoogle_token.jsonúbws_cache.enc.jsonú.anthropic_oauth.jsonúgoogle_oauth_pending.jsonúwebhook_subscriptions.jsoni   i   i  € rN   )z	fal.mediazfal.runzv3.fal.mediazstorage.googleapis.comz*.fal.mediaz	*.fal.run>   r+   r)   r'   r&   r(   r*   ))s   ‰PNG

r&   )s   ÿØÿr'   )s   GIF87ar)   )s   GIF89ar)   )s   BMr+   )NN)NNN)‰ry  Ú__doc__rM  r;  r‚  Ú
contextlibrw   r§   r‹  r­  r"  r±   rü   rú   r  Úurllib.parserf  r   Úpathlibr   Útypingr   r   r   Úfastapir   r	   r
   r   r   r   Úfastapi.responsesr   r   Úhermes_cli._subprocess_compatr   Úhermes_cli.sqlite_safe_readr   r   Úhermes_cli.web_depsr   Úhermes_cli.web_server_filesr   r   r   r   r   r   r   r   Úhermes_cli.web_modelsr   r   r   r   r    Úrouterr!   r"   r#   r$   r%   rI  rL  Ú	frozensetrß  r2  rF   rO   rH   rV   rA  rB  rL  rC  rv   r{   rŒ   Úcontextmanagerr›   r¤   r¹   r¿   rÃ   rÍ   r×   rì   r  r  r,  r7  r>  râ   rQ  r\  rn  r]  rw  r†  r›  rœ  r“  r�  r—  rž  Úpostr´  rË  rÏ  rÔ  rØ  râ  rì  r”  rï  rõ  rø  rÿ  r  r  r  Údeleter%  r²   r³   r˜   r4  r8  rF  rR  rY  r3  rh  ro  rs  rw  rA   )ry  s   @r@   Ú<module>r¢     s�  øðöó Û Û Û Û Û 	Û 	Û Û Û Û Û 
Û Û Ý Ý ß &Ñ &ç M× Mß =å <ß PÝ $÷÷ ó ÷õ ñ 
‹€ñ Ð&Ð(HÓI€ÙÐ(Ð*=Ó>€Ù�=Ð"5Ó6€Ù�
Ð/Ó0€ÙÐ&Ó'€ð ˆK˜ ¨w¸ÀfÈkØˆ\˜6 ?°F¸KÈÐQ_ðÐ ð $Ð á(ò *ó  Ð òÐ ñ %.ò /ó %Ð !ñ  )¨,¸	Ð)BÓCÐ õ8õTð -Ð Ø'Ð ð +Ð ðØˆ#ðØ˜ðØ% uðØ.4°eðØ=CÀUðØLQÐSWðà�	ðà ðà&,¨eðà5<¸fðàFMÈvðð 
ˆ<ðð ! &ðð +1°%ðð :?Àðð KQÐRWðð 
ˆ:ð	ð ˜|¨U°H¸eÀVÈUÐTZØ	ˆ7�F˜E 6¨5°'¸6À5È,Ø
ˆE�6˜6 6¨5°'¸6À6È6ÐSYÐ[bñÐ ðØ
ÐðØ% {ðØ4;¸\ðØKQÐS^ðàˆ\ðà! <ðà17¸ðàFLÐN`ðð Ððð  & |ðð 6<¸[ðð KQÐR]ðð Ð%ð	ð (.¨{ð	ð =CÀOð	ð
 ˆKðð
 ! ,ðð
 18¸ñ€õ1õ)ð ×ÑôHó ðH÷?÷ð& ×Ñô	Gó ð	Gõ	÷Tõõ
õ÷7õ&;õ4õ2ð ‡�ˆLÓô`ó ð`ð8Ð ð Ð õð ‡�ÐÓô&Aó  ð&AõRð$  0Ð Ù!*Ò+]Ó!^Ð ð4Ð ó õ:õõ
 ð ‡�Ð%Ó&ö")ó 'ð")ðJ ‡�ˆLÓöjó ðjõ2Lõ"ð ‡�ÐÓôó ððð
 ÷ð, ‡�Ð!Ó"ôó #ðð& ‡�ÐÓ Ø‡�Ð Ó!ôkó "ó !ðkõ(õð ‡�Ð Ó!ô?ó "ð?õ)ðX ‡�Ð'Ó(ñ ˜C“yÙ�S“	Ù˜4“jö	?ó )ð?ð( ‡�ÐÓ ô?ó !ð?ð ‡�ˆ|ÓôPó ðPð0 ˜Ð!Ø˜Ð#Ø�hÐð€ð ‡�ˆNÓöXó ðXð: ‡�ÐÓ ö'ó !ð'ðT ‡�Ð!Ó"ö5Tó #ð5Tõp;õ	*ð ‡�Ð#Ó$öIó %ðIð2 ‡�ÐÓöó  ðð< ‡�ÐÓö.ó  ð.ð  ‡�Ð!Ó"ö
7ó #ò
7rB   