
    `gjm                    d    d Z ddlmZ ddlmZmZmZmZ ddlm	Z	 ddZ
ddZddZ G d d	      Zy
)u  Shared FAL.ai SDK plumbing.

Holds the stateless atoms that every FAL-backed tool needs:

* :func:`import_fal_client` — lazy import + ``lazy_deps`` integration so
  ``fal_client`` isn't pulled at cold start (it added ~64 ms per CLI
  invocation when imported eagerly).
* :class:`_ManagedFalSyncClient` — wrapper that drives a Nous-managed
  fal-queue gateway through the standard ``fal_client.SyncClient``
  primitives.
* :func:`_normalize_fal_queue_url_format`, :func:`_extract_http_status`
  — small helpers used by both the managed client wrapper and
  ``_submit_fal_request``.

Stateful pieces (cache globals, ``_managed_fal_client*`` selectors,
``_submit_fal_request``) intentionally stay on
:mod:`tools.image_generation_tool`. That module is the patch target for
existing test suites (``tests/tools/test_image_generation.py``,
``tests/tools/test_managed_media_gateways.py``) and for the
``plugins/image_gen/fal/`` plugin's ``_it`` indirection — moving the
caches here would silently defeat ``monkeypatch.setattr(image_tool,
"_managed_fal_client", None)`` because the lookups would go against
``fal_common``'s namespace instead. See the per-rule walkthrough at
issue #26241 for details.
    )annotations)AnyDictOptionalUnion)	urlencodec                     	 ddl m}   | dd       ddl}|S # t        $ r Y t        $ r}t        t	        |            d}~ww xY w)u  Import ``fal_client`` (via ``lazy_deps`` when available) and return
    the module reference.

    Callers are responsible for caching the result on their own module
    global — keeping per-module globals lets tests monkey-patch the
    target module's ``fal_client`` attribute and have the patched value
    stick for that module's call sites.

    Raises :class:`ImportError` if the package is genuinely unavailable.
    r   )ensurez	image.falF)promptN)tools.lazy_depsr
   ImportError	Exceptionstr
fal_client)_lazy_ensureexcr   s      C/root/.hermes/venv/lib/python3.12/site-packages/tools/fal_common.pyimport_fal_clientr   !   sK    $:[/
    $#c(##$s    	AA?Ac                ~    t        | xs d      j                         j                  d      }|st        d      | dS )N /z$Managed FAL queue origin is required)r   striprstrip
ValueError)queue_run_originnormalized_origins     r   _normalize_fal_queue_url_formatr   7   sD    ,2399;BB3G?@@ ""    c                    t        | dd      }|t        |dd      }t        |t              r|S t        | dd      }t        |t              r|S y)u   Return an HTTP status code from httpx/fal exceptions, else None.

    Defensive across exception shapes — httpx.HTTPStatusError exposes
    ``.response.status_code`` while fal_client wrappers may expose
    ``.status_code`` directly.
    responseNstatus_code)getattr
isinstanceint)r   r    statuss      r   _extract_http_statusr&   >   sU     sJ-H=$7fc"MS-.F&#r   c                  N    e Zd ZdZddZddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy)	_ManagedFalSyncClientas  Small per-instance wrapper around ``fal_client.SyncClient`` for
    managed queue hosts.

    The wrapper carries its own ``fal_client`` module reference instead
    of reaching into a module global, so callers stay in control of
    which module's ``fal_client`` is in scope (matters for the test
    patches that swap the legacy module's ``fal_client`` attribute).
    c               Z   t        |dd       }|t        d      t        |dd       }|t        d      t        |      | _         ||      | _        t        | j                  dd       | _        t        |dd       | _        t        |dd       | _        t        |d	d       | _        t        |d
d       | _	        t        |dd       | _
        t        |dd       | _        | j
                  t        d      | j                  | j                  t        d      | j                  t        d      y )N
SyncClientz>fal_client.SyncClient is required for managed FAL gateway modeclientz:fal_client.client is required for managed FAL gateway mode)key_client_maybe_retry_request_raise_for_statusSyncRequestHandleadd_hint_headeradd_priority_headeradd_timeout_headerzFfal_client.SyncClient._client is required for managed FAL gateway modezKfal_client.client request helpers are required for managed FAL gateway modezLfal_client.client.SyncRequestHandle is required for managed FAL gateway mode)r"   RuntimeErrorr   _queue_url_format_sync_client_http_clientr.   r/   _request_handle_class_add_hint_header_add_priority_header_add_timeout_header)selfr   r,   r   sync_client_classclient_modules         r   __init__z_ManagedFalSyncClient.__init__Z   s=   #JdC$_``
Hd; [\\!@AQ!R-#6#D$5$5y$G$+M;QSW$X!!(8KT!R%,]<OQU%V" '7H$ O$+M;PRV$W!#*=:NPT#U $ghh$$,0F0F0Nlmm%%-mnn .r   r   N)pathhintwebhook_urlpriorityheadersstart_timeoutc                  | j                   |z   }	|r|	d|j                  d      z   z  }	||	dt        d|i      z   z  }	t        |xs i       }
|| j                  | j	                  ||
       |)| j
                  t        d      | j                  ||
       |)| j                  t        d      | j                  ||
       | j                  | j                  d|	|t        | j                  dd      |
	      }| j                  |       |j                         }| j                  |d
   |d   |d   |d   | j                        S )Nr   ?fal_webhookzGfal_client.client.add_priority_header is required for priority requestszEfal_client.client.add_timeout_header is required for timeout requestsPOSTdefault_timeoutg      ^@)jsontimeoutrD   
request_idresponse_url
status_url
cancel_url)rM   rN   rO   rP   r+   )r5   lstripr   dictr9   r:   r4   r;   r.   r7   r"   r6   r/   rK   r8   )r<   application	argumentsr@   rA   rB   rC   rD   rE   urlrequest_headersr    datas                r   submitz_ManagedFalSyncClient.submitt   sr    $${23S)))C"3M;#?@@@Cw}"- 5 5 A!!$8((0"#lmm%%h@$''/"#jkk$$]OD,,D--/@%H# - 
 	x(}}))L)n-L)L)$$ * 
 	
r   )r   r   r,   r   r   r   )rS   r   rT   zDict[str, Any]r@   r   rA   Optional[str]rB   rY   rC   r   rD   zOptional[Dict[str, str]]rE   zOptional[Union[int, float]])__name__
__module____qualname____doc__r?   rX    r   r   r(   r(   P   st    o> "%),059/
/
 "/

 /
 /
 #/
 /
 */
 3/
r   r(   N)returnr   )r   r   r_   r   )r   BaseExceptionr_   zOptional[int])r]   
__future__r   typingr   r   r   r   urllib.parser   r   r   r&   r(   r^   r   r   <module>rd      s3   4 # - - ",#$S
 S
r   