
    `gj                       U d Z ddlmZ ddlZddlZddlZddlmZ  ej                  e	      Z
dZdZdZdaded	<    ej                          Zd
addZddZedddZ ed       G d d             Z G d de      Zed
dddZedddZy)a<  Fetch the public petdex manifest.

``https://petdex.dev/api/manifest`` 307-redirects to a JSON document on R2:

    {
      "generatedAt": "...",
      "total": 2926,
      "pets": [
        {"slug": "boba", "displayName": "Boba", "kind": "creature",
         "submittedBy": "railly",
         "spritesheetUrl": "https://assets.petdex.dev/.../spritesheet.webp",
         "petJsonUrl": "https://assets.petdex.dev/.../pet.json",
         "zipUrl": "https://assets.petdex.dev/.../boba.zip"},
        ...
      ]
    }

Read-only and unauthenticated; no credentials involved.
    )annotationsN)	dataclasszhttps://petdex.dev/api/manifestg      $@g     r@z(tuple[float, list[ManifestEntry]] | None_cacheFc                     da y)zDDrop the cached manifest (forces the next fetch to hit the network).N)r        E/root/.hermes/venv/lib/python3.12/site-packages/agent/pet/manifest.pyclear_cacher
   .   s	     Fr   c                 `    t         d uxr% t        j                         t         d   z
  t        k  S )Nr   )r   time	monotonic_MANIFEST_TTLr   r   r	   _cache_is_warmr   4   s'    N$.."2VAY">"NNr   timeoutc                     t               ryt        5  t        r
	 ddd       ydaddd       d fd}t        j                  |dd      j                          y# 1 sw Y   6xY w)u5  Warm the manifest cache in a daemon thread — idempotent, never blocks.

    The desktop picker calls this when it loads the (instant) local-only gallery
    so the full petdex catalog is usually cached by the time it's requested,
    without ever holding up the user's own pets on a network round-trip.
    NTc                     	 t               day # t        $ r"} t        j                  d|        Y d } ~ day d } ~ ww xY w# daw xY w)Nr   z#petdex manifest prefetch failed: %sF)fetch_manifest	Exceptionloggerdebug_prefetching)excr   s    r	   _runzprefetch.<locals>._runI   sJ    	!7+ !L  	ELL>DD L	E !Ls     	=8A  =A   Azpetdex-prefetch)targetnamedaemonreturnNone)r   _prefetch_lockr   	threadingThreadstart)r   r   s   ` r	   prefetchr%   8   s`     	   
! D'8FLLN s   AAA$T)frozenc                  j    e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded<   ded	<   edd
       Zy)ManifestEntryz#A single pet's row in the manifest.strslugdisplay_namekindsubmitted_byspritesheet_urlpet_json_urlzip_urlc                    | t        |j                  dd            j                         t        |j                  dd      xs |j                  dd            t        |j                  dd      xs d      t        |j                  dd      xs d      t        |j                  dd      xs d      t        |j                  dd      xs d      t        |j                  d	d      xs d      
      S )Nr*    displayNamer,   petsubmittedByspritesheetUrl
petJsonUrlzipUrl)r*   r+   r,   r-   r.   r/   r0   )r)   getstrip)clsdatas     r	   	from_dictzManifestEntry.from_dicta   s    TXXfb)*002TXXmR8PDHHVR<PQTXXfb)2U3TXXmR8>B?)92 > D"ETXXlB7=2>2.4"5
 	
r   N)r<   dictr   z'ManifestEntry')__name__
__module____qualname____doc____annotations__classmethodr=   r   r   r	   r(   r(   U   s>    -
I
IL	
 	
r   r(   c                      e Zd ZdZy)ManifestErrorz4Raised when the manifest can't be fetched or parsed.N)r?   r@   rA   rB   r   r   r	   rF   rF   n   s    >r   rF   )r   forcec                   |s4t         .t        j                         t         d   z
  t        k  r	t         d   S 	 ddl}	 |j                  t        | dddi      }|j                          |j                         }t        |t              r|j                  d
      nd}t        |t              st        d      g }|D ]S  }t        |t              st        j!                  |      }	|	j"                  s6|	j$                  sC|j'                  |	       U t        j                         |fa |S # t
        $ r}t        d      |d}~ww xY w# t        $ r}t        d	|       |d}~ww xY w)a  Return every approved pet from the public manifest.

    Cached in-process for ``_MANIFEST_TTL`` seconds (pass ``force=True`` to
    bypass). Follows the 307 redirect to R2.  Raises :class:`ManifestError` on
    any network/parse failure so callers can surface a clean message.
    Nr      z.httpx is required to fetch the petdex manifestTz
User-Agentzhermes-agent-petdex)r   follow_redirectsheadersz!could not fetch petdex manifest: petsz#petdex manifest had no 'pets' array)r   r   r   r   httpxImportErrorrF   r9   MANIFEST_URLraise_for_statusjsonr   
isinstancer>   listr(   r=   r*   r.   append)
r   rG   rM   r   resppayloadrL   entriesrawentrys
             r	   r   r   r   sZ    V'DNN,<vay,H=,XayW
Pyy!!#89	  
 	))+ #-Wd";7;;vDdD!ABB#%G "#t$'',::%//NN5!" nn(FN9  WLMSVVW  P?uEFCOPs.   D( ;E (	E1D==E	E"EE"c                   | j                         j                         } t        |      D ]#  }|j                  j                         | k(  s!|c S  y)z@Return the manifest entry for *slug*, or ``None`` if not listed.r   N)r:   lowerr   r*   )r*   r   rY   s      r	   
find_entryr\      sI    ::<D0 ::%L r   r   )r   bool)r   floatr   r    )r   r^   rG   r]   r   zlist[ManifestEntry])r*   r)   r   r^   r   zManifestEntry | None)rB   
__future__r   loggingr"   r   dataclassesr   	getLoggerr?   r   rO   _DEFAULT_TIMEOUTr   r   rC   Lockr!   r   r
   r   r%   r(   RuntimeErrorrF   r   r\   r   r   r	   <module>rf      s   ( #    !			8	$0  370 7!O "2 O: $
 
 
0?L ? (8u *Z /? r   