+
    kHàj7J  ã                  ó  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIHtHtH	t	H
t
 ^ RIt^ RIHt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 ]P8                  ! ]4      tR	tRs R
]!R&   R R lt" ! R R4      t#]#! 4       t$R t%R R lt&R R lt'R R lt(R<R R llt) ! R R4      t*R R lt+R R lt,R R  lt-R<R! R" llt.R# R$ lt/R<R% R& llt0R' R( lt1R) R* lt2R+ R, lt3R- R. lt4R/R0R1R2R3R/R4 R5 llt5R6t6R7t7R8 R9 lt8 ! R: R;]4      t9R# )=a  Firecrawl web search + extract provider (direct SDK, keyless cloud, or Nous tool-gateway).

Config: ``web.backend`` / ``web.search_backend`` / ``web.extract_backend: firecrawl``.
Env: FIRECRAWL_API_KEY, FIRECRAWL_API_URL (self-hosted), FIRECRAWL_GATEWAY_URL / TOOL_GATEWAY_*.
)ÚannotationsN)ÚAnyÚDictÚListÚOptional)ÚBaseWebSearchProviderÚkeyless_extractÚkeyless_searchÚsearch_failÚ	search_okÚsetup_schema)Úmanaged_tool_gateway)Útool_backend_helpers)Úis_safe_url)Úcheck_website_accesszhttps://api.firecrawl.devzOptional[type]Ú_FIRECRAWL_CLS_CACHEc               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚtype© )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/plugins/web/firecrawl/provider.pyÚ__annotate__r      s   € ÷  ñ  ˜Tñ  ó    c                 ó²   € \         f    ^ RIHp  V ! R4       ^ RIHp Ts \         #   \         d     L\         d   p\        \        T4      4      hRp?ii ; i)uR   Import and cache ``firecrawl.Firecrawl`` (lazy_deps install hint â†’ ImportError).N)Úensure_importÚ	firecrawl)Ú	Firecrawl)r   Úpmr   ÚImportErrorÚ	ExceptionÚstrr   r   )Ú_lazy_ensureÚexcÚ_clss      r   Ú_load_firecrawl_clsr&      sW   € ô Ò#ð	(Ý8á˜Ô%õ
 	0Ø#ÐÜÐøô ô 	ÙÜô 	(Üœc #›hÓ'Ð'ûð	(ús   Š& ¦A³A¼A½AÁAc                  óB   € ] tR t^/tRtRtR R ltR R ltR R ltRt	R	# )
Ú_FirecrawlProxyzJCallable proxy that looks like ``firecrawl.Firecrawl`` but imports lazily.c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úargsr   Úkwargsr   r   )r   s   "r   r   Ú_FirecrawlProxy.__annotate__4   s!   € ÷ 6ñ 6˜cð 6¨Sð 6°Sñ 6r   c                	ó"   € \        4       ! V/ VB # ©N)r&   )Úselfr*   r+   s   &*,r   Ú__call__Ú_FirecrawlProxy.__call__4   s   € Ü"Ô$ dÐ5¨fÑ5Ð5r   c               ó    € V ^8„  d   QhRRRR/# )r   Úobjr   r   Úboolr   )r   s   "r   r   r,   7   s   € ÷ 6ñ 6 Sð 6¨Tñ 6r   c                	ó*   € \        V\        4       4      # r.   )Ú
isinstancer&   )r/   r3   s   &&r   Ú__instancecheck__Ú!_FirecrawlProxy.__instancecheck__7   s   € Ü˜#Ô2Ó4Ó5Ð5r   c               ó   € V ^8„  d   QhRR/# ©r   r   r"   r   )r   s   "r   r   r,   :   s   € ÷ 2ñ 2˜#ñ 2r   c                	ó   € R # )z <lazy firecrawl.Firecrawl proxy>r   ©r/   s   &r   Ú__repr__Ú_FirecrawlProxy.__repr__:   s   € Ù1r   r   N)
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú	__slots__r0   r7   r=   Ú__static_attributes__r   r   r   r(   r(   /   s   † ÙTà€Iõ6õ6÷2ñ 2r   r(   c                 ó   € ^ RI Hp  V # )zbClient cache slots live on tools.web_tools so tests that reset ``_firecrawl_client`` there see it.N)Útools.web_toolsÚ	web_tools)Ú_mods    r   Ú_wtrJ   A   s
   € å"Ø€Kr   c               ó    € V ^8„  d   QhRRRR/# )r   Únamer"   r   r   )r   s   "r   r   r   G   s   € ÷ /ñ /ˆsð /�sñ /r   c                óN   € ^ RI Hp V! V 4      ;'       g    RP                  4       # )é    )Úget_env_valueÚ )Úhermes_cli.configrO   Ústrip)rL   rO   s   & r   Ú_envrS   G   s!   € Ý/Ù˜$Ó×%Ð% 2×,Ñ,Ó.Ð.r   c               ó   € V ^8„  d   QhRR/# )r   r   zOptional[tuple]r   )r   s   "r   r   r   L   s   € ÷ 
ñ 
 oñ 
r   c                 ó@  € \        R4      p \        R4      P                  R4      pV '       g	   V'       dA   RRV 3RV33 UUu/ uF  w  r#V'       g   K  W#bK  	  uppRT;'       g    RT ;'       g    R33# \        4       '       d   R	R\        /R
\        R33# R# u uppi )u  Direct Firecrawl ``(mode, kwargs, cache_key)`` or None. ``mode`` is ``"sdk"`` (keyed / self-hosted) or
``"keyless"`` (explicit selection + no credentials â†’ anonymous public cloud; the explicit selection is
required so an unconfigured install never silently routes to it).ÚFIRECRAWL_API_KEYÚFIRECRAWL_API_URLÚ/ÚsdkÚapi_keyÚapi_urlÚdirectNÚkeylesszdirect-keyless)rS   ÚrstripÚ _is_explicit_firecrawl_selectionÚ_FIRECRAWL_CLOUD_API_URL)rZ   r[   ÚkÚvs       r   Ú_get_direct_firecrawl_configrc   L   sÁ   € ô Ð&Ó'€GÜÐ&Ó'×.Ñ.¨sÓ3€Gß—'Ø¨)°WÐ)=À	È7Ð?SÑ(TÔZÑ(T¡ ÔXY”t�q’tÑ(TÒZÐ]eÐgn×gvÐgvÐrvÐx÷  yHð  yHð  DHð  ]Ið  Ið  	IÜ'×)Ò)Ø˜9Ô&>Ð?ÐBRÔTlÐnrÐAsÐsÐsÙùó [s   ÁBÁBc               ó   € V ^8„  d   QhRR/# ©r   r   r4   r   )r   s   "r   r   r   Y   s   € ÷ ,ñ ,¨$ñ ,r   c                 ó   € ^ RI Hp  V ! R4      # )rN   ©Ú_web_config_selectsr   )Úplugins.web.keyless_mcprh   rg   s    r   r_   r_   Y   s   € Ý;Ù˜{Ó+Ð+r   c               ó    € V ^8„  d   QhRRRR/# ©r   Ú
capabilityúOptional[str]r   r4   r   )r   s   "r   r   r   ^   s   € ÷ (ñ ( -ð (¸4ñ (r   c                óè   a aa€ \        R4      '       g   \        R4      '       d   R# ^ RIHoHo ^ RIHp VV V3R lR 3 F  p V! 4       '       d    R# K  	  V! RR	4      #   \         d     K/  i ; i)
z·Route via the keyless ring only with no direct credentials, when the managed Nous
gateway isn't the selected path for *capability*, and the keyless tier isn't disabled or pinned paid.rV   rW   F©ÚNOUS_MANAGED_PROVIDERÚread_web_capability_selection)Úuse_keylessc                 ó   <€ S! S4      S 8H  # r.   r   )rp   rl   rq   s   €€€r   Ú<lambda>Ú#_use_keyless_ring.<locals>.<lambda>f   s   ø€ Ñ7¸
ÓCÐG\Ò\r   c                 óD   € \        4       ;'       d    \        4       '       * # r.   )Ú_is_tool_gateway_readyr_   r   r   r   rt   ru   g   s   € Ô0Ó2×]Ð]Ô;[Ó;]Ô7]Ð]r   r   rP   )rS   Útools.tool_backend_helpersrp   rq   ri   rr   r!   )rl   rr   Úproberp   rq   s   f  @@r   Ú_use_keyless_ringrz   ^   sp   ú€ ô Ð× Ò ¤DÐ)<×$=Ò$=Ùß_Ý3æ\Ù]ó_ˆð	Ù�wŠwÚñ ñ_ñ �{ BÓ'Ð'øô ô 	Úð	ús   ÁA"Á"A1Á0A1c                  óT   € ] tR t^ptRt]3R R lltR R ltR^/R ltRR	/R
 lt	Rt
R	# )Ú_KeylessFirecrawlClientz�Minimal REST client for Firecrawl's keyless cloud mode; duck-types the SDK's
``search`` / ``scrape`` and never sends an Authorization header.c               ó   € V ^8„  d   QhRR/# )r   r[   r"   r   )r   s   "r   r   Ú$_KeylessFirecrawlClient.__annotate__t   s   € ÷ +ñ + ñ +r   c                	ó2   € VP                  R 4      V n        R# )rX   N)r^   r[   )r/   r[   s   &&r   Ú__init__Ú _KeylessFirecrawlClient.__init__t   s   € Ø—~‘~ cÓ*ˆŽr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úpathr"   Úpayloadúdict[str, Any]r   r   )r   s   "r   r   r~   w   s!   € ÷ ñ ˜#ð ¨ð ¸>ñ r   c                	óx  € \         P                  ! V P                   V 2VR R/RR7      p VP                  4        VP                  4       #   \         P                   dY   p\         P                  ! RTP
                   RTP                  P                  4       R,           2TP                  TR7      ThRp?ii ; i)	zContent-Typezapplication/jsong      N@)ÚjsonÚheadersÚtimeoutzHTTP z: :Ni,  N)ÚrequestÚresponseN)
ÚhttpxÚpostr[   Úraise_for_statusÚHTTPStatusErrorÚstatus_codeÚtextrR   rŠ   r‡   )r/   rƒ   r„   r‹   r$   s   &&&  r   Ú_postÚ_KeylessFirecrawlClient._postw   s½   € Ü—:’: §¡ ¨t¨fÐ5¸GÈnÐ^pÐMqÐ{ô  Aˆð	XØ×%Ñ%Ô'ð �}‰}‹Ðøô ×$Ñ$ô 	Xä×'Ò'¨%°×0DÑ0DÐ/EÀRÈÏÉ×H[ÑH[ÓH]Ð^bÕHcÐGdÐ(eÐor×ozÑozð  FNô  Oð  UXð  Xûð	Xús   ¬A ÁB9Á!AB4Â4B9Úlimitc               	ó.   € V P                  R RVRV/4      # )z
/v2/searchÚqueryr”   ©r’   )r/   r–   r”   s   &$$r   rt   Ú _KeylessFirecrawlClient.<lambda>€   s   € ¨T¯Z©Z¸ÀwÐPUÐW^Ð`eÐFfÔ-gr   r‰   Nc               	óB   € R VRV/pVe   W4R&   V P                  RV4      # )ÚurlÚformatsr‰   z
/v2/scraper—   )r/   rš   r›   r‰   r„   s   &$$$ r   ÚscrapeÚ_KeylessFirecrawlClient.scrape�   s/   € à˜#˜y¨'Ð2ˆØÒØ!(�IÑØ�z‰z˜,¨Ó0Ð0r   ©r[   )r?   r@   rA   rB   rC   r`   r€   r’   Úsearchrœ   rE   r   r   r   r|   r|   p   s5   † ñHð '?÷ +õð h¨!Óg€Fð1¨d÷ 1ð 1r   r|   c               ó   € V ^8„  d   QhRR/# r:   r   )r   s   "r   r   r   ‰   s   € ÷ :ñ : Cñ :r   c                 ó.   € \         P                  ! R 4      # )r   )Ú_gatewayÚbuild_vendor_gateway_urlr   r   r   Ú_get_firecrawl_gateway_urlr¤   ‰   s   € Ü×,Ò,¨[Ó9Ð9r   c               ó   € V ^8„  d   QhRR/# re   r   )r   s   "r   r   r   �   s   € ÷ xñ x ñ xr   c                 óR   € \         P                  ! R\         P                  R7      RJ# )z<True when gateway URL + Nous Subscriber token are available.r   ©Útoken_readerN)r¢   Úresolve_managed_tool_gatewayÚpeek_nous_access_tokenr   r   r   rw   rw   �   s!   € ä×0Ò0°Ì8×KjÑKjÔkÐswÐwÐwr   c               ó   € V ^8„  d   QhRR/# re   r   )r   s   "r   r   r   ’   s   € ÷ ]ñ ] ñ ]r   c                 ó¢   a aa€ ^ RI Ho Ho R V 3R llo\        ;QJ d     VV3R lR 4       F  '       g   K   R# 	  R# ! VV3R lR 4       4      # )znTrue when the route selected via ``hermes tools`` (or, on a never-configured
install, either route) is usable.ro   c               ó   € V ^8„  d   QhRR/# re   r   )r   s   "r   r   Ú-check_firecrawl_api_key.<locals>.__annotate__—   s   € ÷ mñ m˜Tñ mr   c                óz   <€ V S8X  d   \        4       # \        4       R J;'       g    V R J ;'       d    \        4       # r.   )rw   rc   )Úselectedrp   s   &€r   Ú_usableÚ(check_firecrawl_api_key.<locals>._usable—   s<   ø€ ØÐ,Ô,Ü)Ó+Ð+Ü+Ó-°TÐ9×lÐl¸hÈ$Ð>N×>kÐ>kÔSiÓSkÐlr   c              3  ó@   <"  € T F  pS! S! V4      4      x € K  	  R # 5ir.   r   )Ú.0Úcapr±   rq   s   & €€r   Ú	<genexpr>Ú*check_firecrawl_api_key.<locals>.<genexpr>�   s!   øé € Ð\ÑF[¸s‰wÑ4°SÓ9×:Ð:ÓF[ùs   ƒTF)rŸ   Úextract)rx   rp   rq   Úany)rp   r±   rq   s   @@@r   Úcheck_firecrawl_api_keyrº   ’   sB   ú€ ÷ `÷mð m÷ ‹3Õ\ÑF[Ó\�3Œ3Ð\Š3Ð\ˆ3Õ\ÑF[Ó\Ó\Ð\r   c               ó    € V ^8„  d   QhRRRR/# rk   r   )r   s   "r   r   r       s   € ÷ Oñ O ð O¸$ñ Or   c                óŽ   € ^ RI HpHp V! V 4      pVf   \        4       '       d   W18H  # \	        4       RJ ;'       d    \        4       # )uË   True when Firecrawl calls for *capability* go through the Nous Tool Gateway rather than the user's
own key / instance â€” the same decision :func:`_get_firecrawl_client` makes, without building a client.ro   N)rx   rp   rq   r_   rc   rw   )rl   rp   rq   r°   s   &   r   Úis_managed_router½       sD   € ÷ `Ù,¨ZÓ8€HØÒÔ?×AÒAØÑ0Ð0Ü'Ó)¨TÐ1×NÐNÔ6LÓ6NÐNr   c               ó   € V ^8„  d   QhRR/# r:   r   )r   s   "r   r   r   ª   s   € ÷ jñ j¨ñ jr   c                 ó@   € \         P                  ! 4       '       d   R # R# )zc, or use the Nous Tool Gateway via your subscription (FIRECRAWL_GATEWAY_URL or TOOL_GATEWAY_DOMAIN)rP   )Ú_backend_helpersÚmanaged_nous_tools_enabledr   r   r   Ú_firecrawl_backend_help_suffixrÂ   ª   s;   € ô uE÷  u`ò  u`÷  ubò  ubÐpð  jð  hjð  jr   c               ó    € V ^8„  d   QhRRRR/# )r   rl   rm   r   r   r   )r   s   "r   r   r   ®   s   € ÷ / ñ /  mð / ¸sñ / r   c                ó  aaa€ \        4       p^ RIHoHpHo V! V 4      o\        4       pR pR R lpSS8X  d   V! 4       RVV3R lr‡pM0Sf   \        4       '       d   TRVV3R	 lr‡pMVe   TpM
V! 4       R
Tr‡pVf'   \        P                  RX4       \        X! 4       4      hVw  ršp\        VRR4      pVe   \        VRR4      V8X  d   V# V	R8X  d   \        V
R,          R7      M
\        R/ V
B Vn        W±n        VP                  # )u®  Get or create the cached Firecrawl client. Strict selection semantics on the stored selection for
*capability* (``web.<capability>_backend``, else the shared ``web`` selection): ``"nous"`` â†’ managed Tool
Gateway ONLY; any other stored backend â†’ direct Firecrawl ONLY (never a silent managed fallback billed to
Nous); never-configured â†’ direct when present, else managed. Raises ValueError when the resolved path is
unusable.)rp   rq   Úselection_errorc                 óÂ   € \         P                  ! R \         P                  R7      p V f   R# RRV P                  RV P                  /RV P                  V P                  33# )r   r§   NrY   rZ   r[   ztool-gateway)r¢   r©   Úread_nous_access_tokenÚnous_user_tokenÚgateway_origin)Úgws    r   Ú_managedÚ'_get_firecrawl_client.<locals>._managed¹   sl   € Ü×2Ò2°;ÌX×MlÑMlÔmˆØŠ:ÙØ�y "×"4Ñ"4°iÀ×ARÑARÐSÐVdÐfh×fwÑfwÐy{÷  zLñ  zLð  VMð  Mð  	Mr   c               ó   € V ^8„  d   QhRR/# r:   r   )r   s   "r   r   Ú+_get_firecrawl_client.<locals>.__annotate__¿   s   € ÷ uñ u 3ñ ur   c                 ó–   € R p \         P                  ! 4       '       d
   V R,           # V R,           \         P                  ! R4      ,           # )z†Web tools are not configured. Set FIRECRAWL_API_KEY for cloud Firecrawl or set FIRECRAWL_API_URL for a self-hosted Firecrawl instance.z„ With your Nous subscription you can also use the Tool Gateway. run `hermes tools` and select Nous Subscription as the web provider.Ú zmanaged Firecrawl web tools)rÀ   rÁ   Ú%nous_tool_gateway_unavailable_message)Úmessages    r   Ú_unconfigured_messageÚ4_get_firecrawl_client.<locals>._unconfigured_message¿   sJ   € ð [ˆÜ×6Ò6×8Ò8Øð  dõ  dð  dØ˜�}Ô/×UÒUÐVsÓtÕtÐtr   zRthe Nous Subscription web selection is stored but the tool gateway is unavailable.c                 ó   <€ S! R S R4      # )ÚwebzDthe Nous Tool Gateway is not available (not entitled or unreachable)r   )rp   rÅ   s   €€r   rt   Ú'_get_firecrawl_client.<locals>.<lambda>Ç   s   ø€ ñ  L[ØÐ(Ð*pôLrr   NzMdirect Firecrawl selected but FIRECRAWL_API_KEY/FIRECRAWL_API_URL is not set.c                 ó,   <€ S! R S ;'       g    RR4      # )rÖ   r   z6neither FIRECRAWL_API_KEY nor FIRECRAWL_API_URL is setr   )r°   rÅ   s   €€r   rt   r×   Î   s!   ø€ ñ  JYØ�8×*Ð*˜{Ð,dôJfr   z,missing direct config and tool-gateway auth.z*Firecrawl client initialization failed: %sÚ_firecrawl_clientÚ_firecrawl_client_configr]   r[   rž   r   )rJ   rx   rp   rq   rÅ   rc   r_   ÚloggerÚerrorÚ
ValueErrorÚgetattrr|   r   rÙ   rÚ   )rl   Úwtrq   Údirect_configrË   rÓ   ÚresolvedÚlogrÒ   Úclient_moder+   Úclient_configÚcachedrp   r°   rÅ   s   &            @@@r   Ú_get_firecrawl_clientræ   ®   s-  ú€ ô 
‹€BßpÑpÙ,¨ZÓ8€HÜ0Ó2€MòMõuð Ð(Ô(Ù!)£ð  .Bõ Dr�wˆ�wà	Ò	Ô!A×!CÒ!Cð
 "/Ð0õ Bf�wˆ�wà	Ò	"Ø ‰á!)£Ð-[Ð]r�wˆØÒÜ�‰ÐAÀ3ÔGÜ™›Ó#Ð#Ø)1Ñ&€K˜Ü�RÐ,¨dÓ3€FØÒœg bÐ*DÀdÓKÈ}Ô\ØˆØQ\Ð`iÔQiÔ2¸6À)Õ;LÕMÔoxñ  pCð  |Bñ  pC€BÔØ"/ÔØ×ÑÐr   c               ó    € V ^8„  d   QhRRRR/# )r   Úvaluer   r   r   )r   s   "r   r   r   á   s   € ÷ 
ñ 
˜Cð 
 Cñ 
r   c           	     óô   € V e1   \        V \        \        \        \        \
        \        34      '       d   V # RR 3RR 33 F!  w  r\        W4      '       g   K   V! V 4      u # 	  V #   \         d     K5  i ; i)uR   SDK objects (pydantic ``model_dump`` / ``__dict__``) â†’ plain data when possible.Ú
model_dumpc                ó"   € V P                  4       # r.   )rê   )rb   s   &r   rt   Ú"_to_plain_object.<locals>.<lambda>å   s
   € °1·<±<´>r   Ú__dict__c                óœ   € V P                   P                  4        UUu/ uF   w  rVP                  R 4      '       d   K  WbK"  	  upp# u uppi )Ú_)rí   ÚitemsÚ
startswith)rb   ra   Úxs   &  r   rt   rì   å   sb   € Ðmn×mwÑmw×m}Ñm}Ômô  \ZÑmÑeiÐefð  HI÷  HTñ  HTð  UX÷  HYÔ\`Ð\]Ò\`Ñmó  \Zùó  \Zs
   žA¾A)	r6   ÚdictÚlistr"   ÚintÚfloatr4   Úhasattrr!   )rè   ÚattrÚconverts   &  r   Ú_to_plain_objectrú   á   sƒ   € à‚}œ
 5¬4´´s¼CÄÌÐ*M×NÒNØˆØ'Ñ)AÐBÀZñ  RZð  E[ó  \‰ˆÜ�5×ÔðÙ˜u“~Ò%ñ \ð €Løô ô Úðús   ÁA(Á(A7Á6A7c               ó    € V ^8„  d   QhRRRR/# )r   Úvaluesr   r   úlist[dict[str, Any]]r   )r   s   "r   r   r   î   s   € ÷ qñ q 3ð qÐ+?ñ qr   c                ó¬   € \        V \        4      '       d9   \        \        V 4       Uu. uF  p\        V\        4      '       g   K  VNK  	  up# . # u upi r.   )r6   rô   Úmaprú   ró   )rü   Úps   & r   Ú_normalize_result_listr  î   sC   € ÜPZÐ[aÔcg×PhÒPh”sÔ+¨VÔ4ÓLÑ4�!¼
À1Äd×8K�AˆAÑ4ÑLÐpÐnpÐpùÒLs   ©AÁAc               ó    € V ^8„  d   QhRRRR/# )r   r‹   r   r   rý   r   )r   s   "r   r   r   ò   s   € ÷ ñ ¨#ð Ð2Fñ r   c                óü  € \        V 4      p\        V\        4      '       d³   VP                  R4      p\        V\        4      '       d   \        V4      # \        V\        4      '       d#   VP                  R4      VP                  R4      .M. pW1P                  R4      VP                  R4      .,            F  p\        V4      pV'       g   K  Vu # 	  \        V R4      '       d   \        \        V R. 4      4      # . # )z9Search results across SDK/direct/gateway response shapes.ÚdatarÖ   Úresults)rú   r6   ró   Úgetrô   r  r÷   rÞ   )r‹   Úplainr  Ú
candidatesÚ	candidateÚ
normalizeds   &     r   Ú_extract_web_search_resultsr  ò   sÏ   € ä˜XÓ&€EÜ�%œ×ÒØ�y‰y˜Ó ˆÜ�dœD×!Ò!Ü)¨$Ó/Ð/Ü?IÈ$ÔPT×?UÒ?U�d—h‘h˜u“o t§x¡x°	Ó':Ñ;Ð[]ˆ
Ø#§y¡y°Ó'7¸¿¹À9Ó9MÐ&N×NÐNˆIÜ/°	Ó:ˆJß‰zØ!Ò!ñ Oô ˆx˜×ÒÜ%¤g¨h¸¸rÓ&BÓCÐCØ€Ir   c               ó    € V ^8„  d   QhRRRR/# )r   Úscrape_resultr   r   r…   r   )r   s   "r   r   r     s   € ÷ Kñ K¨3ð K°>ñ Kr   c                ó¨   € \        V 4      p\        V\        4      '       g   / # \        VP                  R 4      \        4      '       d
   VR ,          # T# )r  )rú   r6   ró   r  )r  r  s   & r   Ú_extract_scrape_payloadr    sB   € Ü˜]Ó+€EÜ�eœT×"Ò"Øˆ	Ü& u§y¡y°Ó'8¼$×?Ò?ˆ5��=ÐJÀUÐJr   ÚtitlerP   ÚrawFÚblockedc               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   rš   r"   rÜ   r  r  r4   r  zOptional[dict[str, Any]]r   r…   r   )r   s   "r   r   r   
  sD   € ÷ yñ y�cð y #ð y°ð yÀð yÐWoð yð  |Jñ yr   c               óŒ   € V'       d   RR Uu/ uF  qUWE,          bK  	  up/M/ pRV RVRR/V'       d   RR/M/ CRV/CVC# u upi )	z•Per-URL extract failure. ``raw`` adds ``raw_content`` (post-scrape failures carry
it, pre-scrape ones don't); ``blocked`` adds ``blocked_by_policy``.Úblocked_by_policyrš   r  ÚcontentrP   Úraw_contentrÜ   )ÚhostÚruleÚsourcer   )rš   rÜ   r  r  r  ra   Úpolicys   &&$$$  r   Ú_error_entryr  
  sd   € ÷ \cÐ!Ñ;UÓ#VÑ;U°a w¥z¢MÑ;UÑ#VÑWÐhj€FØ�3˜ ¨	°2Ðx×QT¸=È"Ñ:MÐZ\ÐxÐ_fÐhmÑxÐqwÐxÐxùò $Ws   ŽAuc   Scrape timed out after 60s â€” page may be too large or unresponsive. Try browser_navigate instead.z:Blocked: URL targets a private or internal network addressc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   rš   r"   r›   ú	list[str]r   rm   r   r…   r   )r   s   "r   r   r     s(   € ÷ *<ñ *<˜3ð *<¨ð *<¸Mð *<Ènñ *<r   c           
   ƒ  ó0  "  € \        V 4      ;p'       d:   \        P                  RVR,          VR,          4       \        WR,          VR7      #  \        P                  RV 4        \        P
                  ! \        P                  ! \        R4      P                  V VRR	7      ^<R
7      G Rj  x€L
 p\        T4      pTP                  R/ 4      p\        T\        4      '       g0   \!        TR4      '       d   TP#                  4       M\%        TR/ 4      pTP                  RR4      TP                  RT 4      r‡\'        T4      '       g*   \        P                  RT4       \        T\(        TRR7      # \        T4      ;p	'       d<   \        P                  RT	R,          T	R,          4       \        Y‰R,          TRT	R7      # TP                  R4      TP                  R4      rºTR8X  g   Tf   T
'       d   T
MT;'       g    T
;'       g    RpRTRTRTRTRT/#  ELj  \         d*    \        P                  RT 4       \        T \        4      u # i ; i  \*         d8   p\        P-                  RY4       \        T \/        T4      RR7      u Rp?# Rp?ii ; i5i)zžScrape one URL (60s timeout) and re-check SSRF + website policy against the
post-redirect URL. Never raises for scrape errors; returns an error entry instead.z%Blocked web_extract for %s by rule %sr  r  rÒ   )r  zFirecrawl scraping: %sr¸   i`ê  )rš   r›   r‰   )r‰   Nz!Firecrawl scrape timed out for %sÚmetadatarê   rí   r  rP   Ú	sourceURLz7Blocked redirected web_extract for unsafe final URL: %sT)r  r  z0Blocked redirected web_extract for %s by rule %s)r  r  r  ÚmarkdownÚhtmlrš   r  r  z"Firecrawl scrape failed for %s: %s)r  )r   rÛ   Úinfor  ÚasyncioÚwait_forÚ	to_threadræ   rœ   ÚTimeoutErrorÚwarningÚ_SCRAPE_TIMEOUT_MSGr  r  r6   ró   r÷   rê   rÞ   r   Ú_UNSAFE_REDIRECT_MSGr!   Údebugr"   )rš   r›   r   r  r  r„   r   r  Ú	final_urlÚfinal_blockedr"  r#  r  Ú
scrape_errs   &&&           r   Ú_scrape_oner0    sD  é € ô ' sÓ+Ð+€wÖ+Ü�‰Ð;¸WÀV½_ÈgÐV\ÍoÔ^Ü˜C¨Õ!3¸WÔEÐEð$<Ü�‰Ð,¨cÔ2ð	:ô
 #*×"2Ò"2Ü×!Ò!Ü)¨)Ó4×;Ñ;ØØ#Ø"ô	ð ô#÷ ˆMô *¨-Ó8ˆØ—;‘;˜z¨2Ó.ˆä˜(¤D×)Ò)Ü07¸À,×0OÒ0O�x×*Ñ*Ô,ÔU\Ð]eÐgqÐsuÓUvˆHØ#Ÿ<™<¨°Ó4°h·l±lÀ;ÐPSÓ6TˆyÜ˜9×%Ò%Ü�K‰KÐQÐS\Ô]Ü 	Ô+?ÀuÐRVÔWÐWÜ0°Ó;Ð;ˆ=Ö;Ü�K‰KÐJÈMÐZ`ÕLaÐcpÐqwÕcxÔyÜ 	¸Õ+CÈ5ÐVZÐdqÔrÐrØ Ÿ™ ZÓ0°'·+±+¸fÓ2E�$Ø$¨
Ô2°v²~Ï(‘(ÐY]×YoÐYoÐai×YoÐYoÐmoˆØ�y '¨5°)¸WÀmÐU\Ð^hÐjrÐsÐsò5øô ô 	:Ü�N‰NÐ>ÀÔDÜ Ô%8Ó9Ò9ð	:ûô$ ô <Ü�‰Ð9¸3ÔKÜ˜C¤ Z£°dÔ;Õ;ûð<üsŸ   ‚AJÁI Á'AH Â-HÂ.H Â2B>I Å0JÅ1AI Æ>JÆ?3I Ç3
I Ç>	I ÈI ÈJÈH È1IÉI ÉJÉIÉI ÉJÉ,JÊJÊ	JÊJÊJc                  ó^   € ] tR tRtRtRtRtRtRtR R lt	RR R	 llt
R
 R ltR R ltRtR# )ÚFirecrawlWebSearchProvideriB  z9Firecrawl search + extract provider with dual auth paths.r   r   Tc               ó   € V ^8„  d   QhRR/# re   r   )r   s   "r   r   Ú'FirecrawlWebSearchProvider.__annotate__J  s   € ÷ )ñ )˜dñ )r   c                	ó   € \        4       # r.   )rº   r<   s   &r   Úis_availableÚ'FirecrawlWebSearchProvider.is_availableJ  s   € Ü&Ó(Ð(r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r–   r"   r”   rõ   r   r…   r   )r   s   "r   r   r4  M  s&   € ÷ Bñ B˜Cð B¨ð B°Nñ Br   c                óÊ  € ^ RI Hp V! 4       '       d   \        R4      # \        R4      '       d   \	        RRW\
        4      # \
        P                  RW4       \        R4      p \        VP                  WR7      4      p\
        P                  R\        V4      4       \        V4      #   \         d/   p\
        P                  R	T4       \        R
T 24      u Rp?# Rp?ii ; i)z™Pre-flight errors (ValueError / ImportError) propagate so the dispatcher emits
the legacy ``tool_error`` envelope; in-flight errors become failure dicts.©Úis_interruptedÚInterruptedrŸ   r   r   z!Firecrawl search: '%s' (limit=%d))r–   r”   z"Firecrawl: found %d search resultszFirecrawl search error: %szFirecrawl search failed: N)Útools.interruptr;  r
   rz   r	   rÛ   r$  ræ   r  rŸ   Úlenr   r!   r)  )r/   r–   r”   r;  ÚclientÚweb_resultsr$   s   &&&    r   rŸ   Ú!FirecrawlWebSearchProvider.searchM  s¾   € õ 	3Ù×ÒÜ˜}Ó-Ð-Ü˜X×&Ò&Ü! +¨{¸EÌ&ÓQÐQÜ�‰Ð7¸ÔFÜ& xÓ0ˆð	BÜ5°f·m±mÈ%°mÓ6]Ó^ˆKÜ�K‰KÐ<¼cÀ+Ó>NÔOÜ˜[Ó)Ð)øÜô 	BÜ�N‰NÐ7¸Ô=ÜÐ!:¸3¸%Ð@ÓAÕAûð	Bús   Á$AB) Â)C"Â4#CÃC"ÃC"c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úurlsr  r+   r   r   rý   r   )r   s   "r   r   r4  _  s"   € ÷ 
ñ 
 )ð 
°sð 
Ð?Sñ 
r   c           	   ‹  ó¢  "  € ^ RI Hp V! 4       '       d   V Uu. uF  pRVRRRR/NK  	  up# \        R4      '       d+   \        P                  ! \
        RR	V\        4      G R
j  x€L
 # VP                  R4      pVR9   d   V.MRR.pV Uu. uF,  pV! 4       '       d	   RVRRRR/M\        WvV4      G R
j  x€L
 NK.  	  up# u upi  La Lu upi 5i)z{Per-URL scrape; failures become items with an ``error`` field.
``format``: "markdown" | "html" | both (markdown preferred).r:  rš   rÜ   r<  r  rP   r¸   r   r   Nr   r"  r#  )r"  r#  )	r=  r;  rz   r%  r'  r   rÛ   r  r0  )r/   rC  r+   Ú_is_interruptedÚur   r›   rš   s   &&,     r   r¸   Ú"FirecrawlWebSearchProvider.extract_  sã   é € õ 	FÙ×ÒÙMQÓRÉTÈ�U˜A˜w¨°wÀÓCÉTÑRÐRÜ˜Y×'Ò'Ü ×*Ò*¬?¸KÈÐVZÔ\bÓc×cÐcØ—‘˜HÓ%ˆØ$Ð(<Ô<�6‘(À:ÈvÐBVˆñ ó
á�ñ BQ×ARÒARˆU�C˜ -°¸"Ñ=Ô^iÐjmÐx~Ó^×XÒÙñ
ð 	
ùò Sácñ Y@ùò
ùsE   ‚CšC«9CÁ$CÁ%'CÂC
ÂC
Â5C
Â6C
Â>	CÃC
Ã
Cc               ó   € V ^8„  d   QhRR/# )r   r   r…   r   )r   s   "r   r   r4  o  s   € ÷ 
ñ 
 .ñ 
r   c                	ó"   € \        R RRRRR4      # )r   u    keyless/paid Â· optional gatewayzYFull search + extract; supports keyless cloud, direct API, and Nous tool-gateway routing.rV   zBFirecrawl API key (optional; blank = keyless cloud or self-hosted)z'https://docs.firecrawl.dev/introduction)r   r<   s   &r   Úget_setup_schemaÚ+FirecrawlWebSearchProvider.get_setup_schemao  s%   € ÜØÐ;ØgØÐ!eð  hQó
ð 	
r   r   N)é   )r?   r@   rA   rB   rC   ÚNAMEÚDISPLAY_NAMEÚEXTRACTÚKEYLESSr6  rŸ   r¸   rJ  rE   r   r   r   r2  r2  B  s3   † ÙCà€DØ€LØ€GØ€Gõ)÷Bõ$
÷ 
ñ 
r   r2  r.   ):Ú__conditional_annotations__rC   Ú
__future__r   r%  ÚloggingÚtypingr   r   r   r   rŒ   Úplugins.web._commonr   r   r	   r
   r   r   Útoolsr   r¢   r   rÀ   Útools.url_safetyr   Útools.website_policyr   Ú	getLoggerr?   rÛ   r`   r   Ú__annotations__r&   r(   r   rJ   rS   rc   r_   rz   r|   r¤   rw   rº   r½   rÂ   ræ   rú   r  r  r  r  r*  r+  r0  r2  )rQ  s   @r   Ú<module>r[     s
  øðôõ #ã Û ß ,Ó ,ã ç |× |Ý 2Ý :Ý (å 5à	×	Ò	˜8Ó	$€à6Ð ð (,Ð �nÓ +õ ÷"2ñ 2ñ Ó€	òõ/õ

õ,÷
(÷$1ñ 1õ2:õxõ
]÷Oõj÷/ õf
õqõõ"Kðy°rð yÀuð yÐrv÷ yð |Ð ØSÐ õ*<ôZ2
Ð!6ö 2
r   