33from __future__ import annotations
44
55import os
6- from typing import TYPE_CHECKING , Any , Dict , Mapping , cast
6+ from typing import TYPE_CHECKING , Any , Dict , Type , Mapping , cast
77from typing_extensions import Self , Literal , override
88
99import httpx
1414 Omit ,
1515 Timeout ,
1616 NotGiven ,
17+ ResponseT ,
1718 Transport ,
1819 ProxiesTypes ,
1920 RequestOptions ,
2021 not_given ,
2122)
2223from ._utils import is_given , get_async_library
2324from ._compat import cached_property
25+ from ._models import FinalRequestOptions
2426from ._version import __version__
2527from ._streaming import Stream as Stream , AsyncStream as AsyncStream
2628from ._exceptions import KernelError , APIStatusError
2931 SyncAPIClient ,
3032 AsyncAPIClient ,
3133)
34+ from .lib .browser_routing .routing import (
35+ BrowserRouteCache ,
36+ BrowserRoutingConfig ,
37+ strip_direct_vm_auth ,
38+ rewrite_direct_vm_options ,
39+ browser_routing_config_from_env ,
40+ maybe_evict_browser_route_from_response ,
41+ maybe_populate_browser_route_cache_from_response ,
42+ )
3243
3344if TYPE_CHECKING :
3445 from .resources import (
7990class Kernel (SyncAPIClient ):
8091 # client options
8192 api_key : str
93+ browser_route_cache : BrowserRouteCache
8294
8395 _environment : Literal ["production" , "development" ] | NotGiven
96+ _browser_routing : BrowserRoutingConfig
8497
8598 def __init__ (
8699 self ,
@@ -105,6 +118,7 @@ def __init__(
105118 # outlining your use-case to help us decide if it should be
106119 # part of our public interface in the future.
107120 _strict_response_validation : bool = False ,
121+ _browser_route_cache : BrowserRouteCache | None = None ,
108122 ) -> None :
109123 """Construct a new synchronous Kernel client instance.
110124
@@ -154,6 +168,8 @@ def __init__(
154168 custom_query = default_query ,
155169 _strict_response_validation = _strict_response_validation ,
156170 )
171+ self .browser_route_cache = _browser_route_cache or BrowserRouteCache ()
172+ self ._browser_routing = browser_routing_config_from_env ()
157173
158174 @cached_property
159175 def deployments (self ) -> DeploymentsResource :
@@ -266,6 +282,37 @@ def default_headers(self) -> dict[str, str | Omit]:
266282 ** self ._custom_headers ,
267283 }
268284
285+ @override
286+ def _prepare_options (self , options : Any ) -> Any :
287+ options = cast (Any , super ()._prepare_options (options ))
288+ return rewrite_direct_vm_options (options , cache = self .browser_route_cache , config = self ._browser_routing )
289+
290+ @override
291+ def _prepare_request (self , request : httpx .Request ) -> None :
292+ strip_direct_vm_auth (request , cache = self .browser_route_cache )
293+
294+ @override
295+ def _process_response (
296+ self ,
297+ * ,
298+ cast_to : Type [ResponseT ],
299+ options : FinalRequestOptions ,
300+ response : httpx .Response ,
301+ stream : bool ,
302+ stream_cls : type [Stream [Any ]] | type [AsyncStream [Any ]] | None ,
303+ retries_taken : int = 0 ,
304+ ) -> ResponseT :
305+ maybe_populate_browser_route_cache_from_response (response , cache = self .browser_route_cache )
306+ maybe_evict_browser_route_from_response (response , cache = self .browser_route_cache )
307+ return super ()._process_response (
308+ cast_to = cast_to ,
309+ options = options ,
310+ response = response ,
311+ stream = stream ,
312+ stream_cls = stream_cls ,
313+ retries_taken = retries_taken ,
314+ )
315+
269316 def copy (
270317 self ,
271318 * ,
@@ -279,6 +326,7 @@ def copy(
279326 set_default_headers : Mapping [str , str ] | None = None ,
280327 default_query : Mapping [str , object ] | None = None ,
281328 set_default_query : Mapping [str , object ] | None = None ,
329+ _browser_route_cache : BrowserRouteCache | None = None ,
282330 _extra_kwargs : Mapping [str , Any ] = {},
283331 ) -> Self :
284332 """
@@ -312,6 +360,7 @@ def copy(
312360 max_retries = max_retries if is_given (max_retries ) else self .max_retries ,
313361 default_headers = headers ,
314362 default_query = params ,
363+ _browser_route_cache = _browser_route_cache or self .browser_route_cache ,
315364 ** _extra_kwargs ,
316365 )
317366
@@ -356,8 +405,10 @@ def _make_status_error(
356405class AsyncKernel (AsyncAPIClient ):
357406 # client options
358407 api_key : str
408+ browser_route_cache : BrowserRouteCache
359409
360410 _environment : Literal ["production" , "development" ] | NotGiven
411+ _browser_routing : BrowserRoutingConfig
361412
362413 def __init__ (
363414 self ,
@@ -382,6 +433,7 @@ def __init__(
382433 # outlining your use-case to help us decide if it should be
383434 # part of our public interface in the future.
384435 _strict_response_validation : bool = False ,
436+ _browser_route_cache : BrowserRouteCache | None = None ,
385437 ) -> None :
386438 """Construct a new async AsyncKernel client instance.
387439
@@ -431,6 +483,8 @@ def __init__(
431483 custom_query = default_query ,
432484 _strict_response_validation = _strict_response_validation ,
433485 )
486+ self .browser_route_cache = _browser_route_cache or BrowserRouteCache ()
487+ self ._browser_routing = browser_routing_config_from_env ()
434488
435489 @cached_property
436490 def deployments (self ) -> AsyncDeploymentsResource :
@@ -543,6 +597,37 @@ def default_headers(self) -> dict[str, str | Omit]:
543597 ** self ._custom_headers ,
544598 }
545599
600+ @override
601+ async def _prepare_options (self , options : Any ) -> Any :
602+ options = cast (Any , await super ()._prepare_options (options ))
603+ return rewrite_direct_vm_options (options , cache = self .browser_route_cache , config = self ._browser_routing )
604+
605+ @override
606+ async def _prepare_request (self , request : httpx .Request ) -> None :
607+ strip_direct_vm_auth (request , cache = self .browser_route_cache )
608+
609+ @override
610+ async def _process_response (
611+ self ,
612+ * ,
613+ cast_to : Type [ResponseT ],
614+ options : FinalRequestOptions ,
615+ response : httpx .Response ,
616+ stream : bool ,
617+ stream_cls : type [Stream [Any ]] | type [AsyncStream [Any ]] | None ,
618+ retries_taken : int = 0 ,
619+ ) -> ResponseT :
620+ maybe_populate_browser_route_cache_from_response (response , cache = self .browser_route_cache )
621+ maybe_evict_browser_route_from_response (response , cache = self .browser_route_cache )
622+ return await super ()._process_response (
623+ cast_to = cast_to ,
624+ options = options ,
625+ response = response ,
626+ stream = stream ,
627+ stream_cls = stream_cls ,
628+ retries_taken = retries_taken ,
629+ )
630+
546631 def copy (
547632 self ,
548633 * ,
@@ -556,6 +641,7 @@ def copy(
556641 set_default_headers : Mapping [str , str ] | None = None ,
557642 default_query : Mapping [str , object ] | None = None ,
558643 set_default_query : Mapping [str , object ] | None = None ,
644+ _browser_route_cache : BrowserRouteCache | None = None ,
559645 _extra_kwargs : Mapping [str , Any ] = {},
560646 ) -> Self :
561647 """
@@ -589,6 +675,7 @@ def copy(
589675 max_retries = max_retries if is_given (max_retries ) else self .max_retries ,
590676 default_headers = headers ,
591677 default_query = params ,
678+ _browser_route_cache = _browser_route_cache or self .browser_route_cache ,
592679 ** _extra_kwargs ,
593680 )
594681
0 commit comments