
    +j|                        d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ  ej        e          Z G d	 d
          ZdS )uT  
LightClaw — on-demand file download signal handler.

Mirrors: src/socket/handlers.ts L306-436 (``handleFileDownloadReq``).

Protocol (front-end ↔ adapter)::

    Client → Adapter  (kind=file:download, status=download_req):
        { msgId, from, to, content:"", timestamp, kind:"file:download",
          extra: { transferData: { transferId, status:"download_req",
                                    localPath } } }

    Adapter → Client  (kind=file:download, status=download_ready):
        { ..., extra: { transferData: { transferId, status:"download_ready",
                                         name, size, contentType } } }

    Adapter → Client  (kind=file:download, status=download_url):
        { ..., extra: { transferData: { transferId, status:"download_url",
                                         url, name, size, contentType } } }

    Adapter → Client  (kind=file:download, status=download_error):
        { ..., extra: { transferData: { transferId, status:"download_error",
                                         error } } }

Flow:
    1. Parse transferId / localPath from ``data.extra.transferData``.
    2. Validate: localPath must be absolute, must exist, must be a regular
       file.  On failure → ``download_error`` and stop.
    3. Emit ``download_ready`` with the file metadata (name/size/mime).
    4. Upload the file to ``/drive/save`` (server-side content review).
    5. On success → ``download_url`` with the public URL.
       On failure → ``download_error``.

All four reply frames use the reliable emitter (ACK + auto-retry),
matching TS emitWithAck semantics.
    )annotationsN   )DEFAULT_AGENT_IDEVENT_MESSAGE_PRIVATEFileDownloadStatusKIND_FILE_DOWNLOAD)upload_file_to_server)guess_mime_by_ext)resolve_effective_api_keyc                      e Zd ZdZddZdS )	DownloadHandlerMixina$  Mixin providing the ``file:download`` request handler.

    Requires (set by LightClawAdapter):
        self._bot_client_id: str
        self._session: aiohttp.ClientSession
        self._reliable: ReliableEmitter
        self._build_message(...)
        self._emit_reliable(event, data)
    datadictreturnNonec                   K   |                     d          pd|                     d          pt          |                     d          pi }t          |t                    r|                     d          nd}|pi }|                     d          |                     d          pd}t                              d	|           d fddfd}r|s |d           d{V  dS st                              d           dS t          j        	                    |          s |d|            d{V  dS t          j        
                    |          }t          j                            |          s |d|            d{V  dS t          j                            |          s |d|            d{V  dS t          j                            |          }t          j                            |          }t          |          pd}	 t           j        |||	           d{V  t                              d||           	 t%                    }
t'          ||
 j                   d{V \  }}nE# t*          j        $ r  t.          $ r)} |t1          |                     d{V  Y d}~dS d}~ww xY w t           j        ||||	           d{V  t                              d|           dS )zHandle one ``file:download`` ``download_req`` frame.

        Fire-and-forget from ``_handle_raw``; never re-raises.  Three
        outcomes: ``download_ready`` + ``download_url`` on success, or
        ``download_error`` on any failure.
        from agentIdextratransferDataN
transferId	localPathzK[lightclaw] file:download(req) received: transferId=%s localPath=%s from=%sstatusstrr   r   c                0  K   | d}|                     |                               dt          d|i          }	                     t          |           d{V  dS # t
          $ r(}t                              d| |           Y d}~dS d}~ww xY w)z.Emit one file:download reply frame (reliable).)r   r   r   r   )kindagent_idr   Nz?[lightclaw] file:download emit(%s) failed for transferId=%s: %s)update_build_messager   _emit_reliabler   	Exceptionloggerwarning)	r   payloadtransfer_payloadmsgemit_errr   selfsendertransfer_ids	        D/home/agentuser/.hermes/plugins/lightclawbot/src/download_handler.py_replyz>DownloadHandlerMixin._handle_file_download_req.<locals>._replyZ   s      .9VLL##G,,,%%'!%'78	 &  C))*?EEEEEEEEEEE   UK        s    !A# #
B-BBmessagec                ~   K   t                               d|             t          j        |            d {V  d S )Nz2[lightclaw] file:download(error) transferId=%s: %s)error)r#   r0   r   ERROR)r.   r-   r+   s    r,   _reply_errorzDDownloadHandlerMixin._handle_file_download_req.<locals>._reply_errorl   sX      LLDW   &+1AAAAAAAAAAAA    z5Missing transferId or localPath in extra.transferDataz7[lightclaw] file:download(req) missing sender, ignoringz$localPath must be an absolute path: zFile not found: zNot a regular file: zapplication/octet-stream)namesizecontentTypezD[lightclaw] file:download(ready) sent: transferId=%s name=%s size=%d)	sender_id)api_keysession)urlr4   r5   r6   z9[lightclaw] file:download(url) sent: transferId=%s url=%s)r   r   r   r   )r.   r   r   r   )getr   
isinstancer   r#   infor$   ospathisabsrealpathexistsisfilebasenamegetsizer
   r   READYr   r	   _sessionasyncioCancelledErrorr"   r   URL)r)   r   r   td
local_pathr2   resolved	file_namer5   mimer8   _
public_url
upload_errr-   r   r*   r+   s   `             @@@@r,   _handle_file_download_reqz.DownloadHandlerMixin._handle_file_download_reqD   s5      88F##)r88I&&:*:!!'R-7t-D-DN		.)))$bff\**ff[))/R
YV	
 	
 	

	 	 	 	 	 	 	 	 	$	B 	B 	B 	B 	B 	B 	B  	* 	,VWWWWWWWWWF 	NNTUUUFw}}Z(( 	,RjRRSSSSSSSSSF7##J//w~~h'' 	,<(<<=========Fw~~h'' 	,@h@@AAAAAAAAAFG$$X..	wx(( ++I/I f$4
 
 
 	
 	
 	
 	
 	
 	
 	
 	RD	
 	
 	
		/&AAAG"7'4=# # #      MAzz % 	 	 	 	 	 	,s://///////FFFFF	 f"4
 
 
 	
 	
 	
 	
 	
 	
 	
 	G	
 	
 	
 	
 	
s   0J K$KKN)r   r   r   r   )__name__
__module____qualname____doc__rS    r3   r,   r   r   9   s8         c
 c
 c
 c
 c
 c
r3   r   )rW   
__future__r   rH   loggingr>   configr   r   r   r   file_storager	   mediar
   tenancyr   	getLoggerrT   r#   r   rX   r3   r,   <module>r`      s  # #J # " " " " "   				            0 / / / / / $ $ $ $ $ $ . . . . . .		8	$	$n
 n
 n
 n
 n
 n
 n
 n
 n
 n
r3   